apt-get: implement 'autoremove' action.

This commit is contained in:
Aleksei Nikiforov 2017-10-27 18:05:47 +03:00
parent ccdd931577
commit 11a3cc6307
3 changed files with 94 additions and 2 deletions

View File

@ -31,6 +31,7 @@
#include <apti18n.h> #include <apti18n.h>
#include <iostream> #include <iostream>
#include <map>
/*}}}*/ /*}}}*/
using namespace std; using namespace std;
@ -590,7 +591,70 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
return true; return true;
} }
/*}}}*/
static bool all_revdeps_may_be_removed(const pkgDepCache &Cache, const pkgCache::PkgIterator &pkg_iter, std::map<std::string, bool> &states_cache_map)
{
// Don't try to recursively traverse dependency loops
{
auto iter = states_cache_map.find(pkg_iter.Name());
if (iter != states_cache_map.end())
{
return iter->second;
}
}
bool mark_auto = Cache.getMarkAuto(pkg_iter);
// set auto mark to current state (this may be used to get out of infinite dependencies loop
states_cache_map[pkg_iter.Name()] = mark_auto;
// recursively check all dependencies
if (mark_auto)
{
for (pkgCache::DepIterator dep_iter = pkg_iter.RevDependsList(); mark_auto && (not dep_iter.end()); ++dep_iter)
{
// Skip packages not installed
if (dep_iter.ParentPkg()->CurrentState == pkgCache::State::Installed)
{
mark_auto &= all_revdeps_may_be_removed(Cache, dep_iter.ParentPkg(), states_cache_map);
}
}
// update mark to the final value
states_cache_map[pkg_iter.Name()] = mark_auto;
}
return mark_auto;
}
bool pkgAutoremove(pkgDepCache &Cache)
{
if (Cache.BrokenCount() != 0)
{
return false;
}
// Check every installed package
for (pkgCache::PkgIterator pkg_iter = Cache.PkgBegin(); not pkg_iter.end(); ++pkg_iter)
{
// Skip packages not installed
if (pkg_iter->CurrentState == pkgCache::State::Installed)
{
// Keep a cache of dependencies for current package.
// Need to create clean cache for each package,
// otherwise when processing cyclic dependencies
// it may report invalid result and remove actually still needed package
std::map<std::string, bool> states_cache_map;
if (all_revdeps_may_be_removed(Cache, pkg_iter, states_cache_map))
{
Cache.MarkDelete(pkg_iter, _config->FindB("APT::Get::Purge",false));
}
}
}
return true;
}
// ProblemResolver::pkgProblemResolver - Constructor /*{{{*/ // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
// --------------------------------------------------------------------- // ---------------------------------------------------------------------

View File

@ -134,6 +134,7 @@ bool pkgApplyStatus(pkgDepCache &Cache);
bool pkgFixBroken(pkgDepCache &Cache); bool pkgFixBroken(pkgDepCache &Cache);
bool pkgAllUpgrade(pkgDepCache &Cache); bool pkgAllUpgrade(pkgDepCache &Cache);
bool pkgMinimizeUpgrade(pkgDepCache &Cache); bool pkgMinimizeUpgrade(pkgDepCache &Cache);
bool pkgAutoremove(pkgDepCache &Cache);
void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List); void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List);

View File

@ -2525,7 +2525,33 @@ bool DoMoo(CommandLine &CmdL)
return true; return true;
} }
/*}}}*/
bool DoAutoremove(CommandLine &/*CmdL*/)
{
CacheFile Cache(c1out);
if ((not Cache.OpenForInstall()) || (not Cache.CheckDeps()))
{
return false;
}
c0out << _("Calculating Autoremove... ") << std::flush;
if (not pkgAutoremove(*Cache))
{
c0out << _("Failed") << std::endl;
ShowBroken(std::cerr, Cache, false);
return false;
}
if (CheckOnly(Cache))
{
return true;
}
c0out << _("Done") << std::endl;
return InstallPackages(Cache, false);
}
// CNC:2003-03-18 // CNC:2003-03-18
// DoScript - Scripting stuff. /*{{{*/ // DoScript - Scripting stuff. /*{{{*/
@ -2747,6 +2773,7 @@ int main(int argc,const char *argv[])
{"check",&DoCheck}, {"check",&DoCheck},
{"source",&DoSource}, {"source",&DoSource},
{"moo",&DoMoo}, {"moo",&DoMoo},
{"autoremove", &DoAutoremove},
{"help",&ShowHelp}, {"help",&ShowHelp},
// CNC:2003-03-19 // CNC:2003-03-19
#ifdef WITH_LUA #ifdef WITH_LUA