#include <apti18n.h>
-
+#include <sys/types.h>
+#include <regex.h>
#include <iostream>
/*}}}*/
using namespace std;
}
-bool pkgMarkUsed(pkgDepCache &Cache)
+// Helper for APT::NeverAutoRemove, always include the packages matching
+// this regexp into the root-set
+inline bool
+pkgMarkAlwaysInclude(pkgCache::PkgIterator p, vector<regex_t*> alwaysMark)
+{
+ for(unsigned int i=0;i<alwaysMark.size();i++)
+ if (regexec(alwaysMark[i],p.Name(),0,0,0) == 0)
+ return true;
+
+ return false;
+}
+
+// the main mark algorithm
+bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc func)
{
bool follow_recommends;
bool follow_suggests;
{
Cache[p].Marked=false;
Cache[p].Garbage=false;
+
+ // debug output
+ if(_config->FindB("Debug::pkgAutoRemove",false)
+ && Cache[p].Flags & pkgCache::Flag::Auto)
+ std::clog << "AutoDep: " << p.Name() << std::endl;
}
// init vars
follow_recommends=_config->FindB("APT::AutoRemove::RecommendsImportant",false);
- follow_suggests=_config->FindB("APT::AutoRemove::SuggestsImportend", false);
+ follow_suggests=_config->FindB("APT::AutoRemove::SuggestsImportant", false);
- // do the mark part
+ // init the "NeverAutoRemove" variable
+ vector<regex_t *> neverAutoRemoveRegexp;
+ Configuration::Item const *Opts;
+ Opts = _config->Tree("APT::NeverAutoRemove");
+ if (Opts != 0 && Opts->Child != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+
+ regex_t *p = new regex_t;
+ if(regcomp(p,Opts->Value.c_str(),
+ REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
+ {
+ regfree(p);
+ for(unsigned int i=0;i<neverAutoRemoveRegexp.size();i++)
+ regfree(neverAutoRemoveRegexp[i]);
+ return _error->Error("Regex compilation error for APT::NeverAutoRemove");
+ }
+ neverAutoRemoveRegexp.push_back(p);
+ }
+ }
+
+
+ // do the mark part, this is the core bit of the algorithm
for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p)
{
- if(Cache[p].InstallReason==pkgDepCache::Manual ||
- (p->Flags & pkgCache::Flag::Essential))
+ if( (func != NULL ? (*func)(p) : false) ||
+ pkgMarkAlwaysInclude(p, neverAutoRemoveRegexp) ||
+ !(Cache[p].Flags & pkgCache::Flag::Auto) ||
+ (p->Flags & pkgCache::Flag::Essential))
+
{
+ // the package is installed (and set to keep)
if(Cache[p].Keep() && !p.CurrentVer().end())
pkgMarkPackage(Cache, p, p.CurrentVer(),
follow_recommends, follow_suggests);
+ // the package is to be installed
else if(Cache[p].Install())
pkgMarkPackage(Cache, p, Cache[p].InstVerIter(Cache),
follow_recommends, follow_suggests);
{
pkgDepCache::StateCache &state=Cache[p];
- if(!state.Marked)
+ // if it is not marked and it is installed, it's garbage
+ if(!state.Marked && !p.CurrentVer().end())
{
- // mark installed but not yet marked stuff as garbage
- if(p->CurrentVer != 0) {
- state.Garbage=true;
+ state.Garbage=true;
+ if(_config->FindB("Debug::pkgAutoRemove",false))
std::cout << "Garbage: " << p.Name() << std::endl;
- }
-
+
#if 0 // mvo: the below bits still needs to be ported
// Be sure not to re-delete already deleted packages.
#endif
}
}
+
+ // cleanup
+ for(unsigned int i=0;i<neverAutoRemoveRegexp.size();i++)
+ regfree(neverAutoRemoveRegexp[i]);
+
+
return true;
}