summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2024-02-12 14:48:48 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2024-02-13 14:27:27 +0100
commita8352c2859a6f84b36fa5cd0af89231cb656b1ce (patch)
tree69ba18aec6b6a49efd85ef746feb752afc90a780
parent26e0e9b76fb06afe5250eeb8e5b3d069d4793432 (diff)
Add public phased update API
This moves the functions of the PhasedUpgrader class into various other classes so they can be publicly exposed. This introduces three new functions: pkgDepCache::PhasingApplied() tells you whether phasing should be applied to the package. pkgProblemResolver::KeepPhasedUpdates() keeps back updates that have phasing applied. pkgCache::VerIterator::IsSecurityUpdate() determines whether this version contains security fixes.
-rw-r--r--apt-pkg/algorithms.cc20
-rw-r--r--apt-pkg/algorithms.h2
-rw-r--r--apt-pkg/cacheiterators.h1
-rw-r--r--apt-pkg/depcache.cc55
-rw-r--r--apt-pkg/depcache.h6
-rw-r--r--apt-pkg/pkgcache.cc25
-rw-r--r--apt-pkg/upgrade.cc118
-rw-r--r--debian/libapt-pkg6.0.symbols4
8 files changed, 121 insertions, 110 deletions
diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index 3d4096a94..d841d6dd8 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -1246,6 +1246,26 @@ bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I)
return false;
}
/*}}}*/
+// ProblemResolver::KeepPhasedUpdates - Keep back phased updates /*{{{*/
+// ---------------------------------------------------------------------
+// Hold back upgrades to phased versions of already installed packages, unless
+// they are security updates
+bool pkgProblemResolver::KeepPhasedUpdates()
+{
+ for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+ {
+ if (not Cache.PhasingApplied(I))
+ continue;
+
+ Cache.MarkKeep(I, false, false);
+ Cache.MarkProtected(I);
+ Protect(I);
+ }
+
+ return true;
+}
+
+ /*}}}*/
// ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
// ---------------------------------------------------------------------
/* This is the work horse of the soft upgrade routine. It is very gentle
diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h
index f06a38c1b..558beecd3 100644
--- a/apt-pkg/algorithms.h
+++ b/apt-pkg/algorithms.h
@@ -140,6 +140,8 @@ class APT_PUBLIC pkgProblemResolver /*{{{*/
inline void AllowBrokenPolicy(pkgCache::PkgIterator Pkg) { Flags[Pkg->ID] |= BrokenPolicyAllowed; };
#endif
+ bool KeepPhasedUpdates();
+
// Try to intelligently resolve problems by installing and removing packages
bool Resolve(bool BrokenFix = false, OpProgress * const Progress = NULL);
APT_HIDDEN bool ResolveInternal(bool const BrokenFix = false);
diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h
index 9273369bd..074973048 100644
--- a/apt-pkg/cacheiterators.h
+++ b/apt-pkg/cacheiterators.h
@@ -246,6 +246,7 @@ class APT_PUBLIC pkgCache::VerIterator : public Iterator<Version, VerIterator> {
bool Automatic() const;
VerFileIterator NewestFile() const;
+ bool IsSecurityUpdate() const;
#ifdef APT_COMPILING_APT
inline unsigned int PhasedUpdatePercentage() const
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 322bf1bbe..c965781a4 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -30,11 +30,12 @@
#include <algorithm>
#include <iostream>
-#include <memory>
-#include <sstream>
#include <iterator>
#include <list>
+#include <memory>
+#include <random>
#include <set>
+#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
@@ -141,6 +142,7 @@ struct pkgDepCache::Private
{
std::unique_ptr<InRootSetFunc> inRootSetFunc;
std::unique_ptr<APT::CacheFilter::Matcher> IsAVersionedKernelPackage, IsProtectedKernelPackage;
+ std::string machineID;
};
pkgDepCache::pkgDepCache(pkgCache *const pCache, Policy *const Plcy) : group_level(0), Cache(pCache), PkgState(0), DepState(0),
iUsrSize(0), iDownloadSize(0), iInstCount(0), iDelCount(0), iKeepCount(0),
@@ -148,6 +150,7 @@ pkgDepCache::pkgDepCache(pkgCache *const pCache, Policy *const Plcy) : group_lev
{
DebugMarker = _config->FindB("Debug::pkgDepCache::Marker", false);
DebugAutoInstall = _config->FindB("Debug::pkgDepCache::AutoInstall", false);
+ d->machineID = APT::Configuration::getMachineID();
delLocalPolicy = 0;
LocalPolicy = Plcy;
if (LocalPolicy == 0)
@@ -2562,3 +2565,51 @@ bool pkgDepCache::MarkAndSweep()
return false;
}
/*}}}*/
+
+// DepCache::PhasingApplied /*{{{*/
+// Check if this version is a phased update that should be ignored, not considering whether
+// it is a security update.
+static bool IsIgnoredPhasedUpdate(std::string machineID, pkgCache::VerIterator const &Ver)
+{
+ if (_config->FindB("APT::Get::Phase-Policy", false))
+ return false;
+
+ // The order and fallbacks for the always/never checks come from update-manager and exist
+ // to preserve compatibility.
+ if (_config->FindB("APT::Get::Always-Include-Phased-Updates",
+ _config->FindB("Update-Manager::Always-Include-Phased-Updates", false)))
+ return false;
+
+ if (_config->FindB("APT::Get::Never-Include-Phased-Updates",
+ _config->FindB("Update-Manager::Never-Include-Phased-Updates", false)))
+ return true;
+
+ if (machineID.empty() // no machine-id
+ || getenv("SOURCE_DATE_EPOCH") != nullptr // reproducible build - always include
+ || APT::Configuration::isChroot())
+ return false;
+
+ std::string seedStr = std::string(Ver.SourcePkgName()) + "-" + Ver.SourceVerStr() + "-" + machineID;
+ std::seed_seq seed(seedStr.begin(), seedStr.end());
+ std::minstd_rand rand(seed);
+ std::uniform_int_distribution<unsigned int> dist(0, 100);
+
+ return dist(rand) > Ver.PhasedUpdatePercentage();
+}
+
+bool pkgDepCache::PhasingApplied(pkgCache::PkgIterator Pkg) const
+{
+ if (Pkg->CurrentVer == 0)
+ return false;
+ if ((*this)[Pkg].CandidateVer == 0)
+ return false;
+ if ((*this)[Pkg].CandidateVerIter(*Cache).PhasedUpdatePercentage() == 100)
+ return false;
+ if ((*this)[Pkg].CandidateVerIter(*Cache).IsSecurityUpdate())
+ return false;
+ if (!IsIgnoredPhasedUpdate(d->machineID, (*this)[Pkg].CandidateVerIter(*Cache)))
+ return false;
+
+ return true;
+}
+ /*}}}*/
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
index be27b1d77..a850cf91a 100644
--- a/apt-pkg/depcache.h
+++ b/apt-pkg/depcache.h
@@ -381,6 +381,12 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace
bool MarkAndSweep(InRootSetFunc &rootFunc);
bool MarkAndSweep();
+ /** Check if the phased update is ready.
+ *
+ * \return \b false if this is a phased update that is not yet ready for us
+ */
+ bool PhasingApplied(PkgIterator Pkg) const;
+
/** \name State Manipulators
*/
// @{
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index 76336b9b3..06689aa33 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -1017,5 +1017,30 @@ pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
}
/*}}}*/
+// VerIterator::IsSecurity - check if it is a security update /*{{{*/
+// See if this version is a security update. This also checks, for installed packages,
+// if any of the previous versions is a security update
+bool pkgCache::VerIterator::IsSecurityUpdate() const
+{
+ auto Pkg = ParentPkg();
+ auto Installed = Pkg.CurrentVer();
+
+ auto OtherVer = Pkg.VersionList();
+
+ // Advance to first version < our version
+ while (OtherVer->ID != S->ID)
+ ++OtherVer;
+
+ // Iterate over all versions < our version
+ for (; !OtherVer.end() && (Installed.end() || OtherVer->ID != Installed->ID); OtherVer++)
+ {
+ for (auto PF = OtherVer.FileList(); !PF.end(); PF++)
+ if (PF.File() && PF.File().Archive() != nullptr && APT::String::Endswith(PF.File().Archive(), "-security"))
+ return true;
+ }
+ return false;
+}
+
+ /*}}}*/
pkgCache::~pkgCache() {}
diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc
index c7e566a55..fad47838c 100644
--- a/apt-pkg/upgrade.cc
+++ b/apt-pkg/upgrade.cc
@@ -18,101 +18,6 @@
#include <apti18n.h>
/*}}}*/
-struct PhasedUpgrader
-{
- std::string machineID;
- bool isChroot;
-
- PhasedUpgrader()
- {
- machineID = APT::Configuration::getMachineID();
- }
-
- // See if this version is a security update. This also checks, for installed packages,
- // if any of the previous versions is a security update
- bool IsSecurityUpdate(pkgCache::VerIterator const &Ver)
- {
- auto Pkg = Ver.ParentPkg();
- auto Installed = Pkg.CurrentVer();
-
- auto OtherVer = Pkg.VersionList();
-
- // Advance to first version < our version
- while (OtherVer->ID != Ver->ID)
- ++OtherVer;
-
- // Iterate over all versions < our version
- for (; !OtherVer.end() && (Installed.end() || OtherVer->ID != Installed->ID); OtherVer++)
- {
- for (auto PF = OtherVer.FileList(); !PF.end(); PF++)
- if (PF.File() && PF.File().Archive() != nullptr && APT::String::Endswith(PF.File().Archive(), "-security"))
- return true;
- }
- return false;
- }
-
- // Check if this version is a phased update that should be ignored
- bool IsIgnoredPhasedUpdate(pkgCache::VerIterator const &Ver)
- {
- if (_config->FindB("APT::Get::Phase-Policy", false))
- return false;
-
- // The order and fallbacks for the always/never checks come from update-manager and exist
- // to preserve compatibility.
- if (_config->FindB("APT::Get::Always-Include-Phased-Updates",
- _config->FindB("Update-Manager::Always-Include-Phased-Updates", false)))
- return false;
-
- if (_config->FindB("APT::Get::Never-Include-Phased-Updates",
- _config->FindB("Update-Manager::Never-Include-Phased-Updates", false)))
- return true;
-
- if (machineID.empty() // no machine-id
- || getenv("SOURCE_DATE_EPOCH") != nullptr // reproducible build - always include
- || APT::Configuration::isChroot())
- return false;
-
- std::string seedStr = std::string(Ver.SourcePkgName()) + "-" + Ver.SourceVerStr() + "-" + machineID;
- std::seed_seq seed(seedStr.begin(), seedStr.end());
- std::minstd_rand rand(seed);
- std::uniform_int_distribution<unsigned int> dist(0, 100);
-
- return dist(rand) > Ver.PhasedUpdatePercentage();
- }
-
- bool ShouldKeep(pkgDepCache &Cache, pkgCache::PkgIterator Pkg)
- {
- if (Pkg->CurrentVer == 0)
- return false;
- if (Cache[Pkg].CandidateVer == 0)
- return false;
- if (Cache[Pkg].CandidateVerIter(Cache).PhasedUpdatePercentage() == 100)
- return false;
- if (IsSecurityUpdate(Cache[Pkg].CandidateVerIter(Cache)))
- return false;
- if (!IsIgnoredPhasedUpdate(Cache[Pkg].CandidateVerIter(Cache)))
- return false;
-
- return true;
- }
-
- // Hold back upgrades to phased versions of already installed packages, unless
- // they are security updates
- void HoldBackIgnoredPhasedUpdates(pkgDepCache &Cache, pkgProblemResolver *Fix)
- {
- for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
- {
- if (not ShouldKeep(Cache, I))
- continue;
-
- Cache.MarkKeep(I, false, false);
- Cache.MarkProtected(I);
- if (Fix != nullptr)
- Fix->Protect(I);
- }
- }
-};
-
// DistUpgrade - Distribution upgrade /*{{{*/
// ---------------------------------------------------------------------
/* This autoinstalls every package and then force installs every
@@ -132,14 +37,13 @@ static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
pkgDepCache::ActionGroup group(Cache);
- PhasedUpgrader phasedUpgrader;
/* Upgrade all installed packages first without autoinst to help the resolver
in versioned or-groups to upgrade the old solver instead of installing
a new one (if the old solver is not the first one [anymore]) */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
{
- if (phasedUpgrader.ShouldKeep(Cache, I))
+ if (Cache.PhasingApplied(I))
continue;
if (I->CurrentVer != 0)
Cache.MarkInstall(I, false, 0, false);
@@ -152,7 +56,7 @@ static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
for the installation */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
{
- if (phasedUpgrader.ShouldKeep(Cache, I))
+ if (Cache.PhasingApplied(I))
continue;
if (I->CurrentVer != 0)
Cache.MarkInstall(I, true, 0, false);
@@ -184,7 +88,7 @@ static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
if (isEssential == false || instEssential == true)
continue;
pkgCache::PkgIterator P = G.FindPreferredPkg();
- if (phasedUpgrader.ShouldKeep(Cache, P))
+ if (Cache.PhasingApplied(P))
continue;
Cache.MarkInstall(P, true, 0, false);
}
@@ -192,7 +96,7 @@ static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
else if (essential != "none")
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
{
- if (phasedUpgrader.ShouldKeep(Cache, I))
+ if (Cache.PhasingApplied(I))
continue;
if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
Cache.MarkInstall(I, true, 0, false);
@@ -205,7 +109,7 @@ static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
conflict resolution on them all. */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
{
- if (phasedUpgrader.ShouldKeep(Cache, I))
+ if (Cache.PhasingApplied(I))
continue;
if (I->CurrentVer != 0)
Cache.MarkInstall(I, false, 0, false);
@@ -245,7 +149,7 @@ static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
if (Cache[I].InstPolicyBroken())
FixPhasing.AllowBrokenPolicy(I);
- PhasedUpgrader().HoldBackIgnoredPhasedUpdates(Cache, &FixPhasing);
+ FixPhasing.KeepPhasedUpdates();
success = FixPhasing.ResolveByKeepInternal();
}
@@ -267,7 +171,6 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Pr
pkgDepCache::ActionGroup group(Cache);
pkgProblemResolver Fix(&Cache);
- PhasedUpgrader phasedUpgrader;
// Upgrade all installed packages
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
{
@@ -278,7 +181,7 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Pr
if (I->SelectedState == pkgCache::State::Hold)
continue;
- if (phasedUpgrader.ShouldKeep(Cache, I))
+ if (Cache.PhasingApplied(I))
continue;
if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
@@ -288,7 +191,7 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Pr
if (Progress != NULL)
Progress->Progress(50);
- phasedUpgrader.HoldBackIgnoredPhasedUpdates(Cache, &Fix);
+ Fix.KeepPhasedUpdates();
// resolve remaining issues via keep
bool const success = Fix.ResolveByKeepInternal();
@@ -316,7 +219,6 @@ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const
pkgDepCache::ActionGroup group(Cache);
pkgProblemResolver Fix(&Cache);
- PhasedUpgrader phasedUpgrader;
// provide the initial set of stuff we want to upgrade by marking
// all upgradable packages for upgrade
@@ -327,7 +229,7 @@ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const
if (_config->FindB("APT::Ignore-Hold",false) == false)
if (I->SelectedState == pkgCache::State::Hold)
continue;
- if (phasedUpgrader.ShouldKeep(Cache, I))
+ if (Cache.PhasingApplied(I))
continue;
Cache.MarkInstall(I, false, 0, false);
@@ -353,7 +255,7 @@ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const
if (Progress != NULL)
Progress->Progress(60);
- phasedUpgrader.HoldBackIgnoredPhasedUpdates(Cache, &Fix);
+ Fix.KeepPhasedUpdates();
// resolve remaining issues via keep
bool const success = Fix.ResolveByKeepInternal();
diff --git a/debian/libapt-pkg6.0.symbols b/debian/libapt-pkg6.0.symbols
index d297eb1c9..e12f98de7 100644
--- a/debian/libapt-pkg6.0.symbols
+++ b/debian/libapt-pkg6.0.symbols
@@ -1354,6 +1354,10 @@ libapt-pkg.so.6.0 libapt-pkg6.0 #MINVER#
(c++)"vtable for pkgDirStream@APTPKG_6.0" 0.8.0
(c++)"vtable for debDebFile::ControlExtract@APTPKG_6.0" 0.8.0
(c++)"vtable for debDebFile::MemControlExtract@APTPKG_6.0" 0.8.0
+### phased update API
+ (c++)"pkgCache::VerIterator::IsSecurityUpdate() const@APTPKG_6.0" 2.7.11
+ (c++)"pkgDepCache::PhasingApplied(pkgCache::PkgIterator) const@APTPKG_6.0" 2.7.11
+ (c++)"pkgProblemResolver::KeepPhasedUpdates()@APTPKG_6.0" 2.7.11
### gcc artifacts
(c++|optional=std)"void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag)@APTPKG_6.0" 1.7.0~alpha3~
(c++|optional=std)"typeinfo for std::_Mutex_base<(__gnu_cxx::_Lock_policy)2>@APTPKG_6.0" 1.9.11~