From 4326680d2ed23d597f45ca8872a7054368560acc Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 28 Jul 2016 11:43:36 +0200 Subject: simulate all package manager actions explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a planner lets actions to be figured out by dpkg in pending calls these actions aren't mentioned in a simulation. While that might be a good thing for debugging, it would be a change in behavior and especially if a planner avoids explicit removals could be confusing for users. As such we perform the same 'trick' as in the dpkg implementation by performing explicitly what would be done by the pending calls. To save us some work and avoid desyncs we perform a layer violation by using deb/ code in the generic simulation – and further we perform ugly dynamic_cast to avoid breaking the ABI for nothing; aptitude is the only other user of the simulation class according to codesearch.d.n and for that our little trick works. It just isn't working if you happen to extend pkgSimulate or otherwise manage to call the protected Go methods directly – which isn't very realistic/practical. --- apt-pkg/deb/dpkgpm.cc | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d14155d01..4a49774f8 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1297,37 +1297,34 @@ static void cleanUpTmpDir(char * const tmpdir) /*{{{*/ * through to human readable (and i10n-able) * names and calculates a percentage for each step. */ -bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) +static bool ItemIsEssential(pkgDPkgPM::Item const &I) +{ + static auto const cachegen = _config->Find("pkgCacheGen::Essential"); + if (cachegen == "none" || cachegen == "native") + return true; + if (unlikely(I.Pkg.end())) + return true; + return (I.Pkg->Flags & pkgCache::Flag::Essential) != 0; +} +bool pkgDPkgPM::ExpandPendingCalls(std::vector &List, pkgDepCache &Cache) { - // we remove the last configures (and after that removes) from the list here - // as they will be covered by the pending calls, so explicit calls are busy work - decltype(List)::const_iterator::difference_type explicitIdx = - std::distance(List.cbegin(), - _config->FindB("Dpkg::ExplicitLastConfigure", false) ? List.cend() : - std::find_if_not( - std::find_if_not(List.crbegin(), List.crend(), [](Item const &i) { return i.Op == Item::Configure; }), - List.crend(), [](Item const &i) { return i.Op == Item::Remove || i.Op == Item::Purge; }).base()); - - // explicitely remove everything for hookscripts and progress building { std::unordered_set alreadyRemoved; for (auto && I : List) if (I.Op == Item::Remove || I.Op == Item::Purge) alreadyRemoved.insert(I.Pkg->ID); - decltype(List) AppendList; + std::remove_reference::type AppendList; for (auto Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) if (Cache[Pkg].Delete() && alreadyRemoved.insert(Pkg->ID).second == true) AppendList.emplace_back(Cache[Pkg].Purge() ? Item::Purge : Item::Remove, Pkg); std::move(AppendList.begin(), AppendList.end(), std::back_inserter(List)); } - - // explicitely configure everything for hookscripts and progress building { std::unordered_set alreadyConfigured; for (auto && I : List) if (I.Op == Item::Configure) alreadyConfigured.insert(I.Pkg->ID); - decltype(List) AppendList; + std::remove_reference::type AppendList; for (auto && I : List) if (I.Op == Item::Install && alreadyConfigured.insert(I.Pkg->ID).second == true) AppendList.emplace_back(Item::Configure, I.Pkg); @@ -1336,15 +1333,21 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) AppendList.emplace_back(Item::Configure, Pkg); std::move(AppendList.begin(), AppendList.end(), std::back_inserter(List)); } + return true; +} +bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) +{ + // we remove the last configures (and after that removes) from the list here + // as they will be covered by the pending calls, so explicit calls are busy work + decltype(List)::const_iterator::difference_type explicitIdx = + std::distance(List.cbegin(), + _config->FindB("Dpkg::ExplicitLastConfigure", false) ? List.cend() : + std::find_if_not( + std::find_if_not(List.crbegin(), List.crend(), [](Item const &i) { return i.Op == Item::Configure; }), + List.crend(), [](Item const &i) { return i.Op == Item::Remove || i.Op == Item::Purge; }).base()); - auto const ItemIsEssential = [](pkgDPkgPM::Item const &I) { - static auto const cachegen = _config->Find("pkgCacheGen::Essential"); - if (cachegen == "none" || cachegen == "native") - return true; - if (unlikely(I.Pkg.end())) - return true; - return (I.Pkg->Flags & pkgCache::Flag::Essential) != 0; - }; + // explicitely remove&configure everything for hookscripts and progress building + ExpandPendingCalls(List, Cache); auto const StripAlreadyDoneFromPending = [&](APT::VersionVector & Pending) { Pending.erase(std::remove_if(Pending.begin(), Pending.end(), [&](pkgCache::VerIterator const &Ver) { -- cgit v1.2.3