libzypp  17.25.8
PurgeKernels.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <zypp/base/String.h>
14 #include <zypp/base/Logger.h>
15 #include <zypp/base/Regex.h>
16 #include <zypp/base/Iterator.h>
17 #include <zypp/PurgeKernels.h>
18 #include <zypp/PoolQuery.h>
19 #include <zypp/ResPool.h>
20 #include <zypp/Resolver.h>
21 #include <zypp/Filter.h>
22 #include <zypp/ZConfig.h>
23 
24 #include <iostream>
25 #include <fstream>
26 #include <map>
27 #include <unordered_map>
28 #include <sys/utsname.h>
29 #include <functional>
30 #include <array>
31 
32 #undef ZYPP_BASE_LOGGER_LOGGROUP
33 #define ZYPP_BASE_LOGGER_LOGGROUP "PurgeKernels"
34 
35 namespace zypp {
36 
37  using Flavour = std::string;
38  using SolvableList = std::list<sat::Solvable>;
39  using EditionToSolvableMap = std::map<Edition, SolvableList >;
40  using ArchToEditionMap = std::map<Arch, EditionToSolvableMap >;
41 
42  struct GroupInfo {
43 
44  enum GroupType {
45  None, //<< Just here to support default construction
46  Kernels, //<< Map contains kernel packages, so need to receive special handling and flavour matching
47  RelatedBinaries, //<< Map contains related binary packages, so need to receive special handling and flavour matching
48  Sources //<< Map contains source packages, so when matching those against running we ignore the flavour
50 
51  GroupInfo( const GroupType type = None, std::string flav = "") : groupType(type), groupFlavour( std::move(flav) ) { }
52 
53  ArchToEditionMap archToEdMap; //<< Map of actual packages
54  std::string groupFlavour; //<< This would contain a specific flavour if there is one calculated
55  };
56  using GroupMap = std::unordered_map<std::string, GroupInfo>;
57 
59 
60  Impl() {
61  struct utsname unameData;
62  if ( uname( &unameData) == 0 ) {
63 
64  const auto archStr = str::regex_substitute( unameData.machine, str::regex( "^i.86$", str::regex::match_extended ), "i586" );
65 
66  _kernelArch = Arch( archStr );
67  setUnameR( std::string( unameData.release ) );
68 
69  _detectedRunning = true;
70 
71  MIL << "Detected running kernel: " << _runningKernelEdition << " " << _runningKernelFlavour << " " << _kernelArch << std::endl;
72 
73  } else {
74  MIL << "Failed to detect running kernel: " << errno << std::endl;
75  }
76  }
77 
78  void setUnameR ( const std::string &uname ) {
79 
80  _uname_r = uname;
81 
82  MIL << "Set uname " << uname << std::endl;
83 
84  const std::string flavour = str::regex_substitute( _uname_r, str::regex( ".*-", str::regex::match_extended ), "", true );
85  std::string version = str::regex_substitute( _uname_r, str::regex( "-[^-]*$", str::regex::match_extended | str::regex::newline ), "", true );
86 
87  const std::string release = str::regex_substitute( version, str::regex( ".*-", str::regex::match_extended ), "", true );
88 
89  version = str::regex_substitute( version, str::regex( "-[^-]*$", str::regex::match_extended | str::regex::newline ), "", true );
90 
91  // from purge-kernels script, was copied from kernel-source/rpm/mkspec
92  version = str::regex_substitute( version, str::regex( "\\.0-rc", str::regex::match_extended ), ".rc", true );
93  version = str::regex_substitute( version, str::regex( "-rc\\d+", str::regex::match_extended ), "", true );
94  version = str::regex_substitute( version, str::regex( "-", str::regex::match_extended ), ".", true );
95 
96  _runningKernelEdition = Edition( version, release );
97  _runningKernelFlavour = flavour;
98 
99  MIL << "Parsed info from uname: " << std::endl;
100  MIL << "Kernel Flavour: " << _runningKernelFlavour << std::endl;
101  MIL << "Kernel Edition: " << _runningKernelEdition << std::endl;
102  }
103 
104  bool removePackageAndCheck( const sat::Solvable slv, const std::set<sat::Solvable> &keepList , const std::set<sat::Solvable> &removeList ) const;
105  static bool versionMatch ( const Edition &a, const Edition &b );
106  void parseKeepSpec();
107  void fillKeepList(const GroupMap &installedKernels, std::set<sat::Solvable> &keepList , std::set<sat::Solvable> &removeList ) const;
108 
109  std::set<size_t> _keepLatestOffsets = { 0 };
110  std::set<size_t> _keepOldestOffsets;
111  std::set<Edition> _keepSpecificEditions;
112  std::string _uname_r;
117  bool _keepRunning = true;
118  bool _detectedRunning = false;
119  };
120 
125  bool PurgeKernels::Impl::removePackageAndCheck( const sat::Solvable slv, const std::set<sat::Solvable> &keepList , const std::set<sat::Solvable> &removeList ) const
126  {
127  const filter::ByStatus toBeUninstalledFilter( &ResStatus::isToBeUninstalled );
128 
129  PoolItem pi ( slv );
130 
131  auto pool = ResPool::instance();
132 
133  // make sure the pool is clean
134  if ( !pool.resolver().resolvePool() ) {
135  MIL << "Pool failed to resolve, not doing anything" << std::endl;
136  return false;
137  }
138 
139  MIL << "Request to remove package: " << pi << std::endl;
140 
141  //list of packages that are allowed to be removed automatically.
142  const str::regex validRemovals("(kernel-syms(-.*)?|kgraft-patch(-.*)?|kernel-livepatch(-.*)?|.*-kmp(-.*)?)");
143 
144  if ( pi.status().isLocked() ) {
145  MIL << "Package " << pi << " is locked by the user, not removing." << std::endl;
146  return false;
147  }
148 
149  //remember which packages are already marked for removal, we do not need to check them again
150  std::set<sat::Solvable> currentSetOfRemovals;
151  for ( const PoolItem & p : pool.byStatus( toBeUninstalledFilter ) ) {
152  currentSetOfRemovals.insert( p.satSolvable() );
153  }
154 
156 
157  if ( !pool.resolver().resolvePool() ) {
158  MIL << "Failed to resolve pool, skipping " << pi << std::endl;
159  pool.resolver().problems();
160  pi.statusReset();
161 
162  return false;
163  }
164 
165  std::set<sat::Solvable> removedInThisRun;
166  removedInThisRun.insert( slv );
167 
168  for ( const PoolItem & p : pool.byStatus( toBeUninstalledFilter ) ) {
169 
170  //check if that package is removeable
171  if ( p.status().isByUser() //this was set by us, ignore it
172  || (currentSetOfRemovals.find( p.satSolvable() ) != currentSetOfRemovals.end()) //this was marked by a previous removal, ignore them
173  )
174  continue;
175 
176  // remember for later we need remove the debugsource and debuginfo packages as well
177  removedInThisRun.insert( p.satSolvable() );
178 
179  MIL << "Package " << p << " was marked by the solver for removal." << std::endl;
180 
181  // if we do not plan to remove that package anyway, we need to check if its allowed to be removed ( package in removelist can never be in keep list )
182  if ( removeList.find( p.satSolvable() ) != removeList.end() )
183  continue;
184 
185  if ( keepList.find( p.satSolvable() ) != keepList.end() ) {
186  MIL << "Package " << p << " is in keep spec, skipping" << pi << std::endl;
187  pi.statusReset();
188  return false;
189  }
190 
191  str::smatch what;
192  if ( !str::regex_match( p.name(), what, validRemovals) ) {
193  MIL << "Package " << p << " should not be removed, skipping " << pi << std::endl;
194  pi.statusReset();
195  return false;
196  }
197  }
198 
199  MIL << "Successfully marked package: " << pi << " for removal."<<std::endl;
200 
201  //now check and mark the -debugsource and -debuginfo packages for this package and all the packages that were removed. Maybe collect it before and just remove here
202  MIL << "Trying to remove debuginfo for: " << pi <<"."<<std::endl;
203  for ( sat::Solvable solvable : removedInThisRun ) {
204 
205  if ( solvable.arch() == Arch_noarch ||
206  solvable.arch() == Arch_empty )
207  continue;
208 
209  for ( const char * suffix : { "-debugsource", "-debuginfo" } ) {
210  PoolQuery q;
212  q.addDependency( sat::SolvAttr::provides, Capability( solvable.name()+suffix, Rel::EQ, solvable.edition() ) );
213  q.setInstalledOnly();
214  q.setMatchExact();
215 
216  for ( sat::Solvable debugPackage : q ) {
217 
218  if ( debugPackage.arch() != solvable.arch() )
219  continue;
220 
221  MIL << "Found debug package for " << solvable << " : " << debugPackage << std::endl;
222  //if removing the package fails it will not stop us from going on , so no need to check
223  removePackageAndCheck( debugPackage, keepList, removeList );
224  }
225  }
226  }
227  MIL << "Finished removing debuginfo for: " << pi <<"."<<std::endl;
228 
229  return true;
230  }
231 
236  {
237  if ( a == b )
238  return true;
239 
240  // the build counter should not be considered here, so if there is one we cut it off
241  const str::regex buildCntRegex( "\\.[0-9]+($|\\.g[0-9a-f]{7}$)", str::regex::match_extended );
242 
243  std::string versionStr = b.asString();
244  str::smatch matches;
245  if ( buildCntRegex.matches( versionStr.data(), matches ) ) {
246  if ( matches.size() >= 2 ) {
247  versionStr.replace( matches.begin(0), (matches.end(0) - matches.begin(0))+1, matches[1] );
248  return a == Edition(versionStr);
249  }
250  }
251  return false;
252  }
253 
258  {
259  //keep spec parse regex, make sure to edit the group offsets if changing this regex
260  const str::regex specRegex( "^(latest|oldest)([+-][0-9]+)?$", str::regex::match_extended );
261 
262  const unsigned tokenGrp = 1; //index of the group matching the token
263  const unsigned modifierGrp = 2; //index of the group matching the offset modifier
264 
265 
266  MIL << "Parsing keep spec: " << _keepSpec << std::endl;
267 
268  std::vector<std::string> words;
269  str::split( _keepSpec, std::back_inserter(words), ",", str::TRIM );
270  if ( words.empty() ) {
271  WAR << "Invalid keep spec: " << _keepSpec << " using default latest,running." << std::endl;
272  return;
273  }
274 
275  _keepRunning = false;
276  _keepLatestOffsets.clear();
277  _keepOldestOffsets.clear();
278 
279  for ( const std::string &word : words ) {
280  if ( word == "running" ) {
281  _keepRunning = true;
282  } else {
283  str::smatch what;
284  if ( !str::regex_match( word, what, specRegex ) ) {
285  _keepSpecificEditions.insert( Edition(word) );
286  continue;
287  }
288 
289  auto addKeepOff = []( const auto &off, auto &set, const auto &constraint ){
290  const off_t num = off.empty() ? 0 : str::strtonum<off_t>( off );
291  if ( !constraint(num) ) return false;
292  set.insert( static_cast<size_t>(std::abs(num)) );
293  return true;
294  };
295 
296  if ( what[tokenGrp] == "oldest" ) {
297  addKeepOff( what[modifierGrp], _keepOldestOffsets, [ &word ]( off_t num ) {
298  if ( num < 0 ) {
299  WAR << "Ignoring invalid modifier in keep spec: " << word << ", oldest supports only positive modifiers." << std::endl;
300  return false;
301  }
302  return true;
303  });
304  } else {
305  addKeepOff( what[modifierGrp], _keepLatestOffsets, [ &word ]( off_t num ) {
306  if ( num > 0 ) {
307  WAR << "Ignoring invalid modifier in keep spec: " << word << ", latest supports only negative modifiers." << std::endl;
308  return false;
309  }
310  return true;
311  });
312  }
313  }
314  }
315  }
316 
326  void PurgeKernels::Impl::fillKeepList( const GroupMap &installedKernels, std::set<sat::Solvable> &keepList, std::set<sat::Solvable> &removeList ) const
327  {
328 
329  const auto markAsKeep = [ &keepList, &removeList ]( sat::Solvable pck ) {
330  MIL << "Marking package " << pck << " as to keep." << std::endl;
331  keepList.insert( pck ) ;
332  removeList.erase( pck );
333  };
334 
335  const auto versionPredicate = []( const auto &edition ){
336  return [ &edition ]( const auto &elem ) {
337  return versionMatch( edition, elem.first );
338  };
339  };
340 
341  for ( const auto &groupInfo : installedKernels ) {
342 
343  MIL << "Starting with group " << groupInfo.first << std::endl;
344 
345  for ( const auto &archMap : groupInfo.second.archToEdMap ) {
346 
347  MIL << "Starting with arch " << archMap.first << std::endl;
348 
349  size_t currOff = 0; //the current "oldest" offset ( runs from map start to end )
350  size_t currROff = archMap.second.size() - 1; // the current "latest" offset ( runs from map end to start )
351 
352 
353  const EditionToSolvableMap &map = archMap.second;
354 
355  if ( _keepRunning
356  && ( ( archMap.first == _kernelArch && groupInfo.second.groupFlavour == _runningKernelFlavour )
357  || groupInfo.second.groupType == GroupInfo::Sources ) ) {
358 
359  MIL << "Matching packages against running kernel "<< _runningKernelEdition << "-" << _runningKernelFlavour << "-" <<_kernelArch << std::endl;
360 
361  auto it = std::find_if( map.begin(), map.end(), versionPredicate( _runningKernelEdition ) );
362  if ( it == map.end() ) {
363 
364  // If we look at Sources we cannot match the flavour but we still want to keep on checking the rest of the keep spec
365  if ( groupInfo.second.groupType != GroupInfo::Sources ) {
366  MIL << "Running kernel "<< _runningKernelEdition << "-" << _runningKernelFlavour << "-" <<_kernelArch << " not installed."<<std::endl;
367  MIL << "NOT removing any packages for flavor "<<_runningKernelFlavour<<"-"<<_kernelArch<<" ."<<std::endl;
368 
369  for ( const auto &kernelMap : map ) {
370  for( sat::Solvable pck : kernelMap.second )
371  markAsKeep(pck);
372  }
373  continue;
374  }
375 
376  } else {
377  // there could be multiple matches here because of rebuild counter, lets try to find the last one
378  MIL << "Found possible running candidate edition: " << it->first << std::endl;
379  auto nit = it;
380  for ( nit++ ; nit != map.end() && versionMatch( _runningKernelEdition, nit->first ) ; nit++ ) {
381  MIL << "Found possible more recent running candidate edition: " << nit->first << std::endl;
382  it = nit;
383  }
384  }
385 
386  // mark all packages of the running version as keep
387  if ( it != map.end() ) {
388  for( sat::Solvable pck : it->second ) {
389  markAsKeep(pck);
390  }
391  }
392  }
393 
394  for ( const auto &kernelMap : map ) {
395  //if we find one of the running offsets in the keepspec, we add the kernel id the the list of packages to keep
396  if ( _keepOldestOffsets.find( currOff ) != _keepOldestOffsets.end() || _keepLatestOffsets.find( currROff ) != _keepLatestOffsets.end() ) {
397  std::for_each( kernelMap.second.begin(), kernelMap.second.end(), markAsKeep );
398  }
399  currOff++;
400  currROff--;
401 
402  // a kernel package might be explicitely locked by version
403  // We need to go over all package name provides ( provides is named like the package ) and match
404  // them against the specified version to know which ones to keep. (bsc#1176740 bsc#1176192)
405  std::for_each( kernelMap.second.begin(), kernelMap.second.end(), [ & ]( sat::Solvable solv ){
406  for ( Capability prov : solv.provides() ) {
407  if ( prov.detail().name() == solv.name() && _keepSpecificEditions.count( prov.detail().ed() ) ) {
408  markAsKeep( solv );
409  }
410  }
411  });
412  }
413  }
414  }
415  }
416 
418  : _pimpl( new Impl() )
419  {
420 
421  }
422 
424  {
425  MIL << std::endl << "--------------------- Starting to mark obsolete kernels ---------------------"<<std::endl;
426 
427  if ( _pimpl->_keepSpec.empty() ) {
428  WAR << "Keep spec is empty, removing nothing." << std::endl;
429  return;
430  }
431 
433 
435  WAR << "Unable to detect running kernel, but keeping the running kernel was requested. Not removing any packages." << std::endl;
436  return;
437  }
438 
439  auto pool = ResPool::instance();
440  pool.resolver().setForceResolve( true ); // set allow uninstall flag
441 
442  const filter::ByStatus toBeUninstalledFilter( &ResStatus::isToBeUninstalled );
443 
444  // kernel flavour regex
445  const str::regex kernelFlavourRegex("^kernel-(.*)$");
446 
447  // the map of all installed kernel packages, grouped by Flavour -> Arch -> Version -> (List of all packages in that category)
448  // devel and source packages are grouped together
449  GroupMap installedKrnlPackages;
450 
451 
452  // packages that we plan to remove
453  std::set<sat::Solvable> packagesToRemove;
454 
455  const auto addPackageToMap = [&installedKrnlPackages, &packagesToRemove] ( const GroupInfo::GroupType type, const std::string &ident, const std::string &flavour, const sat::Solvable &installedKrnlPck ) {
456 
457  if ( !installedKrnlPackages.count( ident ) )
458  installedKrnlPackages.insert( std::make_pair( ident, GroupInfo(type, flavour) ) );
459 
460  auto &groupInfo = installedKrnlPackages[ ident ];
461  if ( groupInfo.groupType != type || groupInfo.groupFlavour != flavour ) {
462  ERR << "Got inconsistent type and flavour for ident this is a BUG: " << ident << std::endl
463  << "Original Flavour-Type: "<<groupInfo.groupFlavour<<"-"<<groupInfo.groupType << std::endl
464  << "Competing Flavour-Type: "<< flavour << "-" << type << std::endl;
465  }
466 
467  const auto currArch = installedKrnlPck.arch();
468  if ( !groupInfo.archToEdMap.count( currArch ) )
469  groupInfo.archToEdMap.insert( std::make_pair( currArch , EditionToSolvableMap {} ) );
470 
471  auto &editionToSolvableMap = groupInfo.archToEdMap[ currArch ];
472 
473  // calculate the "shortest" or most generic edition of all the package name provides
474  // ( the key of the provides is the package name ). This generic edition is used to
475  // group the packages together. This should get us around the issue that uname -r does
476  // not represent the actual rpm package version anymore. ( bsc#1176740 )
477  auto currCount = INT_MAX;
478  Edition edToUse;
479  for ( Capability prov : installedKrnlPck.provides() ) {
480  if ( prov.detail().name() == installedKrnlPck.name() ) {
481  if ( edToUse == Edition::noedition ) {
482  edToUse = installedKrnlPck.edition();
483  const auto &relStr = edToUse.release();
484  currCount = std::count( relStr.begin(), relStr.end(), '.');
485  } else {
486  const auto &pckEd = prov.detail().ed();
487  const auto &relStr = pckEd.release();
488  if ( const auto pntCnt = std::count( relStr.begin(), relStr.end(), '.'); pntCnt < currCount ) {
489  currCount = pntCnt;
490  edToUse = pckEd;
491  }
492  }
493  }
494  }
495 
496  if ( !editionToSolvableMap.count( edToUse ) )
497  editionToSolvableMap.insert( std::make_pair( edToUse, SolvableList{} ) );
498 
499  editionToSolvableMap[edToUse].push_back( installedKrnlPck );
500 
501  //in the first step we collect all packages in this list, then later we will remove the packages we want to explicitely keep
502  packagesToRemove.insert( installedKrnlPck );
503  };
504 
505  // the set of satSolvables that have to be kept always
506  std::set<sat::Solvable> packagesToKeep;
507 
508  //collect the list of installed kernel packages
509  PoolQuery q;
511  q.addAttribute( sat::SolvAttr::provides, "multiversion(kernel)" );
512  q.setInstalledOnly();
513  q.setMatchExact();
514 
515  MIL << "Searching for obsolete multiversion kernel packages." << std::endl;
516 
517  for ( sat::Solvable installedKrnlPck : q ) {
518 
519  MIL << "Found installed multiversion kernel package " << installedKrnlPck << std::endl;
520 
521  if ( installedKrnlPck.provides().matches(Capability("kernel-uname-r")) ) {
522  MIL << "Identified as a kernel package " << std::endl;
523 
524  // we group kernel packages by flavour
525  str::smatch what;
526  str::regex_match( installedKrnlPck.name(), what, kernelFlavourRegex );
527  if ( what[1].empty() ) {
528  WAR << "Could not detect flavour for: " << installedKrnlPck << " ...skipping" << std::endl;
529  continue;
530  }
531 
532  std::string flavour = what[1];
533 
534  // XXX: No dashes in flavor names
535  const auto dash = flavour.find_first_of('-');
536  if ( dash != std::string::npos ) {
537  flavour = flavour.substr( 0, dash );
538  }
539 
540  // the ident for kernels is the flavour, to also handle cases like kernel-base and kernel which should be in the same group handled together
541  addPackageToMap( GroupInfo::Kernels, flavour, flavour, installedKrnlPck );
542 
543  } else {
544 
545  // if adapting the groups do not forget to explicitely handle the group when querying the matches
546  const str::regex explicitelyHandled("kernel-syms(-.*)?|kernel(-.*)?-devel");
547 
548  MIL << "Not a kernel package, inspecting more closely " << std::endl;
549 
550  // we directly handle all noarch packages that export multiversion(kernel)
551  if ( installedKrnlPck.arch() == Arch_noarch ) {
552 
553  MIL << "Handling package explicitely due to architecture (noarch)."<< std::endl;
554  addPackageToMap( GroupInfo::Sources, installedKrnlPck.name(), "", installedKrnlPck );
555 
556  } else if ( str::smatch match; str::regex_match( installedKrnlPck.name(), match, explicitelyHandled ) ) {
557 
558  // try to get the flavour from the name
559  // if we have a kernel-syms getting no flavour means we have the "default" one, otherwise we use the flavour
560  // getting no flavour for a kernel(-*)?-devel means we have the kernel-devel package otherwise the flavour specific one
561  // ...yes this is horrible
562  std::string flav;
563 
564  // first group match is a kernel-syms
565  if ( match.size() > 1 && match[1].size() )
566  flav = match[1].substr(1);
567  // second group match is a kernel-flavour-devel
568  else if ( match.size() > 2 && match[2].size() )
569  flav = match[2].substr(1);
570  else if ( installedKrnlPck.name() == "kernel-syms" )
571  flav = "default";
572 
573  MIL << "Handling package explicitely due to name match."<< std::endl;
574  addPackageToMap ( GroupInfo::RelatedBinaries, installedKrnlPck.name(), flav, installedKrnlPck );
575  } else {
576  MIL << "Package not explicitely handled" << std::endl;
577  }
578  }
579 
580  }
581 
582  MIL << "Grouped packages: " << std::endl;
583  std::for_each( installedKrnlPackages.begin(), installedKrnlPackages.end(),[]( const auto &ident ){
584  MIL << "\tGroup ident: "<<ident.first<<std::endl;
585  MIL << "\t Group type: "<<ident.second.groupType<<std::endl;
586  MIL << "\t Group flav: "<<ident.second.groupFlavour<<std::endl;
587  std::for_each( ident.second.archToEdMap.begin(), ident.second.archToEdMap.end(), []( const auto &arch) {
588  MIL << "\t\tArch: "<<arch.first<<std::endl;
589  std::for_each( arch.second.begin(), arch.second.end(), []( const auto &edition) {
590  MIL << "\t\t\tEdition: "<<edition.first<<std::endl;
591  std::for_each( edition.second.begin(), edition.second.end(), []( const auto &packageId) {
592  MIL << "\t\t\t\t "<<sat::Solvable(packageId)<<std::endl;
593  });
594  });
595  });
596  });
597 
598  _pimpl->fillKeepList( installedKrnlPackages, packagesToKeep, packagesToRemove );
599 
600  for ( sat::Solvable slv : packagesToRemove )
601  _pimpl->removePackageAndCheck( slv, packagesToKeep, packagesToRemove );
602  }
603 
604  void PurgeKernels::setUnameR( const std::string &val )
605  {
606  _pimpl->setUnameR( val );
607  }
608 
609  std::string PurgeKernels::unameR() const
610  {
611  return _pimpl->_uname_r;
612  }
613 
615  {
616  _pimpl->_kernelArch = arch;
617  }
618 
620  {
621  return _pimpl->_kernelArch;
622  }
623 
624  void PurgeKernels::setKeepSpec( const std::string &val )
625  {
626  _pimpl->_keepSpec = val;
627  }
628 
629  std::string PurgeKernels::keepSpec() const
630  {
631  return _pimpl->_keepSpec;
632  }
633 
634 }
ResPool.h
zypp::PoolItem
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:51
PurgeKernels.h
zypp::str::regex::matches
bool matches(const char *s, str::smatch &matches, int flags=none) const
Definition: Regex.cc:57
zypp::sat::Solvable
A Solvable object within the sat Pool.
Definition: Solvable.h:54
zypp::filter::ByStatus
Filter solvables according to their status.
Definition: Filter.h:142
zypp::PurgeKernels::keepSpec
std::string keepSpec() const
Definition: PurgeKernels.cc:629
zypp::PurgeKernels::unameR
std::string unameR() const
Definition: PurgeKernels.cc:609
zypp::GroupInfo::groupType
enum zypp::GroupInfo::GroupType groupType
zypp::str::regex_substitute
std::string regex_substitute(const std::string &s, const regex &regex, const std::string &replacement, bool global=true)
Replaces the matched regex with the string passed in replacement.
Definition: Regex.cc:120
zypp::PoolQuery
Meta-data query API.
Definition: PoolQuery.h:91
zypp::PurgeKernels::markObsoleteKernels
void markObsoleteKernels()
Definition: PurgeKernels.cc:423
zypp::PoolQuery::addAttribute
void addAttribute(const sat::SolvAttr &attr, const std::string &value="")
Filter by the value of the specified attr attribute.
Definition: PoolQuery.cc:873
zypp::PurgeKernels::Impl::Impl
Impl()
Definition: PurgeKernels.cc:60
zypp::PurgeKernels::Impl::parseKeepSpec
void parseKeepSpec()
Definition: PurgeKernels.cc:257
zypp::GroupInfo::Kernels
@ Kernels
Definition: PurgeKernels.cc:46
zypp::PurgeKernels::Impl::_keepOldestOffsets
std::set< size_t > _keepOldestOffsets
Definition: PurgeKernels.cc:110
zypp::PoolQuery::addDependency
void addDependency(const sat::SolvAttr &attr, const std::string &name, const Rel &op, const Edition &edition)
Query "name|global op edition".
Definition: PoolQuery.cc:876
ZConfig.h
zypp::GroupInfo::groupFlavour
std::string groupFlavour
Definition: PurgeKernels.cc:54
zypp::GroupInfo::Sources
@ Sources
Definition: PurgeKernels.cc:48
MIL
#define MIL
Definition: Logger.h:91
zypp::Flavour
std::string Flavour
Definition: PurgeKernels.cc:37
zypp::Edition
Edition represents [epoch:]version[-release]
Definition: Edition.h:61
zypp::ArchToEditionMap
std::map< Arch, EditionToSolvableMap > ArchToEditionMap
Definition: PurgeKernels.cc:40
zypp::ResKind::package
static const ResKind package
Definition: ResKind.h:40
zypp::str::regex::newline
@ newline
Match newline.
Definition: Regex.h:102
zypp::GroupInfo::archToEdMap
ArchToEditionMap archToEdMap
Definition: PurgeKernels.cc:53
zypp::ZConfig::multiversionKernels
std::string multiversionKernels() const
Definition: ZConfig.cc:1202
zypp::ResPool::instance
static ResPool instance()
Singleton ctor.
Definition: ResPool.cc:37
zypp::str::smatch::begin
std::string::size_type begin(unsigned i) const
Begin index of subexpression i in match_str (or std::string::npos)
Definition: Regex.cc:97
zypp::PurgeKernels::Impl::versionMatch
static bool versionMatch(const Edition &a, const Edition &b)
Definition: PurgeKernels.cc:235
zypp::PoolQuery::addKind
void addKind(const ResKind &kind)
Filter by selectable kind.
Definition: PoolQuery.cc:867
zypp::PurgeKernels::Impl::_keepLatestOffsets
std::set< size_t > _keepLatestOffsets
Definition: PurgeKernels.cc:109
zypp::PurgeKernels::Impl::_keepSpec
std::string _keepSpec
Definition: PurgeKernels.cc:116
zypp::Arch
Architecture.
Definition: Arch.h:37
zypp::PurgeKernels::Impl::_keepSpecificEditions
std::set< Edition > _keepSpecificEditions
Definition: PurgeKernels.cc:111
zypp::str::TRIM
@ TRIM
Definition: String.h:497
zypp::Edition::release
std::string release() const
Release.
Definition: Edition.cc:110
zypp::EditionToSolvableMap
std::map< Edition, SolvableList > EditionToSolvableMap
Definition: PurgeKernels.cc:39
zypp::PurgeKernels::setUnameR
void setUnameR(const std::string &val)
Definition: PurgeKernels.cc:604
zypp::GroupInfo::GroupType
GroupType
Definition: PurgeKernels.cc:44
Resolver.h
zypp::str::split
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.
Definition: String.h:527
Logger.h
zypp::PurgeKernels::Impl::removePackageAndCheck
bool removePackageAndCheck(const sat::Solvable slv, const std::set< sat::Solvable > &keepList, const std::set< sat::Solvable > &removeList) const
Definition: PurgeKernels.cc:125
WAR
#define WAR
Definition: Logger.h:92
zypp::GroupMap
std::unordered_map< std::string, GroupInfo > GroupMap
Definition: PurgeKernels.cc:56
zypp::str::smatch::end
std::string::size_type end(unsigned i) const
End index of subexpression i in match_str (or std::string::npos)
Definition: Regex.cc:100
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:126
zypp::PoolQuery::setInstalledOnly
void setInstalledOnly()
Return only @System repo packages.
Definition: PoolQuery.cc:963
zypp::PurgeKernels::kernelArch
Arch kernelArch() const
Definition: PurgeKernels.cc:619
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
zypp::PurgeKernels::Impl::setUnameR
void setUnameR(const std::string &uname)
Definition: PurgeKernels.cc:78
zypp::GroupInfo::RelatedBinaries
@ RelatedBinaries
Definition: PurgeKernels.cc:47
PoolQuery.h
Regex.h
zypp::PurgeKernels::Impl::_keepRunning
bool _keepRunning
Definition: PurgeKernels.cc:117
zypp::PurgeKernels::PurgeKernels
PurgeKernels()
Definition: PurgeKernels.cc:417
zypp::PurgeKernels::_pimpl
RW_pointer< Impl > _pimpl
Definition: PurgeKernels.h:66
zypp::ResStatus::setToBeUninstalled
bool setToBeUninstalled(TransactByValue causer)
Definition: ResStatus.h:545
zypp::IdStringType::asString
std::string asString() const
Definition: IdStringType.h:106
zypp::str::smatch
Regular expression match result.
Definition: Regex.h:163
Iterator.h
zypp::Rel::EQ
static const Rel EQ
Definition: Rel.h:50
zypp::PurgeKernels::Impl::_detectedRunning
bool _detectedRunning
Definition: PurgeKernels.cc:118
zypp::PurgeKernels::setKeepSpec
void setKeepSpec(const std::string &val)
Definition: PurgeKernels.cc:624
zypp::GroupInfo
Definition: PurgeKernels.cc:42
zypp::Edition::noedition
static const Edition noedition
Value representing noedition ("") This is in fact a valid Edition.
Definition: Edition.h:73
zypp::Capability
A sat capability.
Definition: Capability.h:60
std
Definition: Arch.h:348
zypp::ResStatus::USER
@ USER
Definition: ResStatus.h:111
zypp::PoolItem::status
ResStatus & status() const
Returns the current status.
Definition: PoolItem.cc:204
zypp::ResStatus::isToBeUninstalled
bool isToBeUninstalled() const
Definition: ResStatus.h:261
zypp::str::regex::match_extended
@ match_extended
Use POSIX Extended Regular Expression syntax when interpreting regex.
Definition: Regex.h:101
zypp::GroupInfo::None
@ None
Definition: PurgeKernels.cc:45
zypp::PurgeKernels::Impl
Definition: PurgeKernels.cc:58
String.h
zypp::ResStatus::isLocked
bool isLocked() const
Definition: ResStatus.h:264
zypp::sat::SolvAttr::provides
static const SolvAttr provides
Definition: SolvAttr.h:60
zypp::PoolQuery::setMatchExact
void setMatchExact()
Set to match exact string instead of substring.
Definition: PoolQuery.cc:952
ERR
#define ERR
Definition: Logger.h:93
zypp::PurgeKernels::setKernelArch
void setKernelArch(const zypp::Arch &arch)
Definition: PurgeKernels.cc:614
zypp::Arch_empty
const Arch Arch_empty(IdString::Empty)
zypp::PurgeKernels::Impl::_uname_r
std::string _uname_r
Definition: PurgeKernels.cc:112
zypp::PurgeKernels::Impl::_runningKernelFlavour
Flavour _runningKernelFlavour
Definition: PurgeKernels.cc:114
zypp::SolvableList
std::list< sat::Solvable > SolvableList
Definition: PurgeKernels.cc:38
zypp::str::regex_match
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
Definition: Regex.h:70
zypp::str::smatch::size
unsigned size() const
Definition: Regex.cc:106
zypp::GroupInfo::GroupInfo
GroupInfo(const GroupType type=None, std::string flav="")
Definition: PurgeKernels.cc:51
zypp::str::regex
Regular expression.
Definition: Regex.h:95
zypp::PurgeKernels::Impl::_kernelArch
Arch _kernelArch
Definition: PurgeKernels.cc:115
zypp::PurgeKernels::Impl::fillKeepList
void fillKeepList(const GroupMap &installedKernels, std::set< sat::Solvable > &keepList, std::set< sat::Solvable > &removeList) const
Definition: PurgeKernels.cc:326
zypp::PurgeKernels::Impl::_runningKernelEdition
Edition _runningKernelEdition
Definition: PurgeKernels.cc:113
zypp::PoolItem::statusReset
ResStatus & statusReset() const
Reset status.
Definition: PoolItem.cc:205
Filter.h