summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2016-04-09 13:30:59 +0200
committerJulian Andres Klode <jak@debian.org>2016-08-31 13:49:37 +0200
commit3880929d386eb93e390543e44bf4abdde2ec8c78 (patch)
tree26538a6798cc3388c963ff9d94bf7cdeeb599217
parent43e01d61c2f9872536ff8b879b58ae367d2ec8cb (diff)
more explicit MarkRequired algorithm code (part 2)
As the previous commit, this shouldn't change behavior at all, but beside being more explicit and perhaps faster its also considerably shorter (granted, mostly by if0-block elimination). Gbp-Dch: Ignore (cherry picked from commit 5a3339db48479114a0e1e11ebc8d640eb3e49933)
-rw-r--r--apt-pkg/depcache.cc184
1 files changed, 68 insertions, 116 deletions
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index ee40b879c..eb8f6460d 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -1824,6 +1824,20 @@ bool pkgDepCache::MarkFollowsSuggests()
}
// pkgDepCache::MarkRequired - the main mark algorithm /*{{{*/
+static bool IsPkgInBoringState(pkgCache::PkgIterator const &Pkg, pkgDepCache::StateCache const * const PkgState)
+{
+ if (Pkg->CurrentVer == 0)
+ {
+ if (PkgState[Pkg->ID].Keep())
+ return true;
+ }
+ else
+ {
+ if (PkgState[Pkg->ID].Delete())
+ return true;
+ }
+ return false;
+}
bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
{
if (_config->Find("APT::Solver", "internal") != "internal")
@@ -1832,8 +1846,8 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false);
// init the states
- map_id_t const PackagesCount = Head().PackageCount;
- for(map_id_t i = 0; i < PackagesCount; ++i)
+ auto const PackagesCount = Head().PackageCount;
+ for(auto i = decltype(PackagesCount){0}; i < PackagesCount; ++i)
{
PkgState[i].Marked = false;
PkgState[i].Garbage = false;
@@ -1849,16 +1863,8 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
// do the mark part, this is the core bit of the algorithm
for (PkgIterator P = PkgBegin(); !P.end(); ++P)
{
- if (P->CurrentVer == 0)
- {
- if (PkgState[P->ID].Keep())
- continue;
- }
- else
- {
- if (PkgState[P->ID].Delete())
- continue;
- }
+ if (PkgState[P->ID].Marked || IsPkgInBoringState(P, PkgState))
+ continue;
if ((PkgState[P->ID].Flags & Flag::Auto) == 0)
;
@@ -1888,124 +1894,70 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
}
/*}}}*/
// MarkPackage - mark a single package in Mark-and-Sweep /*{{{*/
-void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
- const pkgCache::VerIterator &ver,
+void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &Pkg,
+ const pkgCache::VerIterator &Ver,
bool const &follow_recommends,
bool const &follow_suggests)
{
- pkgDepCache::StateCache &state = PkgState[pkg->ID];
+ {
+ pkgDepCache::StateCache &state = PkgState[Pkg->ID];
+ // if we are marked already we are done
+ if(state.Marked || unlikely(Ver.end()))
+ return;
+ state.Marked=true;
+ }
- // if we are marked already we are done
- if(state.Marked)
+ if (IsPkgInBoringState(Pkg, PkgState))
return;
- VerIterator const currver = pkg.CurrentVer();
- VerIterator const instver = state.InstVerIter(*this);
-
-#if 0
- VerIterator const candver = state.CandidateVerIter(*this);
+ bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false);
+ if(debug_autoremove)
+ std::clog << "Marking: " << Pkg.FullName() << " " << Ver.VerStr() << std::endl;
- // 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 = Unused)
+ for (auto D = Ver.DependsList(); D.end() == false; ++D)
{
- if(ver==candver)
- mark_install(pkg, false, false, NULL);
- else if(ver==pkg.CurrentVer())
- MarkKeep(pkg, false, false);
-
- instver=state.InstVerIter(*this);
- }
-#endif
+ auto const T = D.TargetPkg();
+ if (PkgState[T->ID].Marked)
+ continue;
- // For packages that are not going to be removed, ignore versions
- // other than the InstVer. For packages that are going to be
- // removed, ignore versions other than the current version.
- if(!(ver == instver && !instver.end()) &&
- !(ver == currver && instver.end() && !ver.end()))
- return;
+ if (D->Type != Dep::Depends &&
+ D->Type != Dep::PreDepends &&
+ (follow_recommends == false || D->Type != Dep::Recommends) &&
+ (follow_suggests == false || D->Type != Dep::Suggests))
+ continue;
- bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false);
+ // handle the virtual part first
+ for(auto Prv = T.ProvidesList(); Prv.end() == false; ++Prv)
+ {
+ auto PP = Prv.OwnerPkg();
+ if (PkgState[PP->ID].Marked || IsPkgInBoringState(PP, PkgState))
+ continue;
- if(debug_autoremove)
- {
- std::clog << "Marking: " << pkg.FullName();
- if(!ver.end())
- std::clog << " " << ver.VerStr();
- if(!currver.end())
- std::clog << ", Curr=" << currver.VerStr();
- if(!instver.end())
- std::clog << ", Inst=" << instver.VerStr();
- std::clog << std::endl;
- }
+ // we want to ignore provides from uninteresting versions
+ auto const PV = (PkgState[PP->ID].Install()) ?
+ PkgState[PP->ID].InstVerIter(*this) : PP.CurrentVer();
+ if (unlikely(PV.end()) || PV != Prv.OwnerVer() || D.IsSatisfied(Prv) == false)
+ continue;
- state.Marked=true;
+ if (debug_autoremove)
+ std::clog << "Following dep: " << APT::PrettyDep(this, D)
+ << ", provided by " << PP.FullName() << " " << PV.VerStr() << std::endl;
+ MarkPackage(PP, PV, follow_recommends, follow_suggests);
+ }
- if(ver.end() == true)
- return;
+ // now deal with the real part of the package
+ if (IsPkgInBoringState(T, PkgState))
+ continue;
- for(DepIterator d = ver.DependsList(); !d.end(); ++d)
- {
- if(d->Type == Dep::Depends ||
- d->Type == Dep::PreDepends ||
- (follow_recommends &&
- d->Type == Dep::Recommends) ||
- (follow_suggests &&
- d->Type == Dep::Suggests))
- {
- // Try all versions of this package.
- for(VerIterator V = d.TargetPkg().VersionList();
- !V.end(); ++V)
- {
- if(d.IsSatisfied(V))
- {
- if(debug_autoremove)
- {
- std::clog << "Following dep: " << d.ParentPkg().FullName()
- << " " << d.ParentVer().VerStr() << " "
- << d.DepType() << " " << d.TargetPkg().FullName();
- if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
- {
- std::clog << " (" << d.CompType() << " "
- << d.TargetVer() << ")";
- }
- std::clog << std::endl;
- }
- MarkPackage(V.ParentPkg(), V,
- follow_recommends, follow_suggests);
- }
- }
- // Now try virtual packages
- for(PrvIterator prv=d.TargetPkg().ProvidesList();
- !prv.end(); ++prv)
- {
- if(d.IsSatisfied(prv))
- {
- if(debug_autoremove)
- {
- std::clog << "Following dep: " << d.ParentPkg().FullName() << " "
- << d.ParentVer().VerStr() << " "
- << d.DepType() << " " << d.TargetPkg().FullName() << " ";
- if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
- {
- std::clog << " (" << d.CompType() << " "
- << d.TargetVer() << ")";
- }
- std::clog << ", provided by "
- << prv.OwnerPkg().FullName() << " "
- << prv.OwnerVer().VerStr()
- << std::endl;
- }
-
- MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
- follow_recommends, follow_suggests);
- }
- }
- }
- }
+ auto const TV = (PkgState[T->ID].Install()) ?
+ PkgState[T->ID].InstVerIter(*this) : T.CurrentVer();
+ if (unlikely(TV.end()) || D.IsSatisfied(TV) == false)
+ continue;
+
+ if (debug_autoremove)
+ std::clog << "Following dep: " << APT::PrettyDep(this, D) << std::endl;
+ MarkPackage(T, TV, follow_recommends, follow_suggests);
+ }
}
/*}}}*/
bool pkgDepCache::Sweep() /*{{{*/