-
-// mark a single package in Mark-and-Sweep
-void pkgMarkPackage(pkgDepCache &Cache,
- const pkgCache::PkgIterator &pkg,
- const pkgCache::VerIterator &ver,
- bool follow_recommends,
- bool follow_suggests)
-{
- pkgDepCache::StateCache &state=Cache[pkg];
- pkgCache::VerIterator candver=state.CandidateVerIter(Cache);
- pkgCache::VerIterator instver=state.InstVerIter(Cache);
-
-#if 0
- // If a package was garbage-collected but is now being marked, we
- // should re-select it
- // For cases when a pkg is set to upgrade and this trigger the
- // removal of a no-longer used dependency. if the pkg is set to
- // keep again later it will result in broken deps
- if(state.Delete() && state.RemoveReason=pkgDepCache::Unused)
- {
- if(ver==candver)
- mark_install(pkg, false, false, NULL);
- else if(ver==pkg.CurrentVer())
- MarkKeep(pkg);
-
- instver=state.InstVerIter(*this);
- }
-#endif
-
- // Ignore versions other than the InstVer, and ignore packages
- // that are already going to be removed or just left uninstalled.
- if(!(ver==instver && !instver.end()))
- return;
-
- // if we are marked already we are done
- if(state.Marked)
- return;
-
- //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
- state.Marked=true;
-
- if(!ver.end())
- {
- for(pkgCache::DepIterator d=ver.DependsList(); !d.end(); ++d)
- {
- if(d->Type==pkgCache::Dep::Depends ||
- d->Type==pkgCache::Dep::PreDepends ||
- (follow_recommends &&
- d->Type==pkgCache::Dep::Recommends) ||
- (follow_suggests &&
- d->Type==pkgCache::Dep::Suggests))
- {
- // Try all versions of this package.
- for(pkgCache::VerIterator V=d.TargetPkg().VersionList();
- !V.end(); ++V)
- {
- if(_system->VS->CheckDep(V.VerStr(),d->CompareOp, d.TargetVer()))
- {
- pkgMarkPackage(Cache, V.ParentPkg(), V,
- follow_recommends, follow_suggests);
- }
- }
- // Now try virtual packages
- for(pkgCache::PrvIterator prv=d.TargetPkg().ProvidesList();
- !prv.end(); ++prv)
- {
- if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp,
- d.TargetVer()))
- {
- pkgMarkPackage(Cache, prv.OwnerPkg(), prv.OwnerVer(),
- follow_recommends, follow_suggests);
- }
- }
- }
- }
- }
-}
-
-
-// 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;
-
- // init the states
- for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p)
- {
- 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::SuggestsImportant", false);
-
-
- // 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( (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);
- }
- }
-
-
- // do the sweep
- for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p)
- {
- pkgDepCache::StateCache &state=Cache[p];
-
- // if it is not marked and it is installed, it's garbage
- if(!state.Marked && !p.CurrentVer().end())
- {
- 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.
- if(delete_unused && (!p.CurrentVer().end() || state.Install()) &&
- !state.Delete())
- {
- bool do_delete=true;
-
- // If the package is being upgraded, check if we're
- // losing a versioned dep. If the dependency matches
- // the previous version and not the new version, keep
- // the package back instead of removing it.
- if(!p.CurrentVer().end() && state.Install())
- {
- const char *vs=p.CurrentVer().VerStr();
-
- // Check direct revdeps only. THIS ASSUMES NO
- // VERSIONED PROVIDES, but Debian probably won't
- // have them for ages if ever.
- for(pkgCache::DepIterator revdep=p.RevDependsList();
- !revdep.end(); ++revdep)
- {
- pkgCache::PkgIterator depender=revdep.ParentPkg();
- // Find which version of the depending package
- // will be installed.
- pkgCache::VerIterator instver=(*this)[depender].InstVerIter(*this);
-
- // Only pay attention to strong positive
- // dependencies whose parents will be installed.
- if(revdep.ParentVer()==instver &&
- (revdep->Type==pkgCache::Dep::Depends ||
- revdep->Type==pkgCache::Dep::PreDepends ||
- (revdep->Type==pkgCache::Dep::Recommends &&
- follow_recommends)))
- {
- // If the previous version matched, cancel the
- // deletion. (note that I assume that the new
- // version does NOT match; otherwise it would
- // not be unused!)
- if(_system->VS->CheckDep(vs,
- revdep->CompareOp,
- revdep.TargetVer()))
- {
- mark_keep(p, false, false, undo);
- do_delete=false;
- break;
- }
- }
- }
- }
-
- if(do_delete)
- mark_delete(p, false, true, undo);
- }
-#endif
- }
- }
-
- // cleanup
- for(unsigned int i=0;i<neverAutoRemoveRegexp.size();i++)
- regfree(neverAutoRemoveRegexp[i]);
-
-
- return true;
-}