From a8352c2859a6f84b36fa5cd0af89231cb656b1ce Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 12 Feb 2024 14:48:48 +0100 Subject: 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. --- apt-pkg/algorithms.cc | 20 ++++++++ apt-pkg/algorithms.h | 2 + apt-pkg/cacheiterators.h | 1 + apt-pkg/depcache.cc | 55 +++++++++++++++++++- apt-pkg/depcache.h | 6 +++ apt-pkg/pkgcache.cc | 25 +++++++++ apt-pkg/upgrade.cc | 118 ++++--------------------------------------- debian/libapt-pkg6.0.symbols | 4 ++ 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 @@ -1245,6 +1245,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 /*{{{*/ // --------------------------------------------------------------------- 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 { 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 #include -#include -#include #include #include +#include +#include #include +#include #include #include #include @@ -141,6 +142,7 @@ struct pkgDepCache::Private { std::unique_ptr inRootSetFunc; std::unique_ptr 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 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 /*}}}*/ -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 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, std::allocator >::_M_construct(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~ -- cgit v1.2.3-70-g09d2 From 422e68f569f374f697b84332f7e68c6fe5f7389f Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 13 Feb 2024 12:29:28 +0100 Subject: Add a new ?phasing pattern This selects all packages that are being kept back due to phasing on your system. --- apt-pkg/cachefilter-patterns.cc | 2 ++ apt-pkg/cachefilter-patterns.h | 10 ++++++++++ doc/apt-patterns.7.xml | 3 +++ test/integration/test-phased-updates-upgrade | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index faf5735b8..6ef34c953 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -498,6 +498,8 @@ std::unique_ptr PatternParser::aPattern(std::unique_p return std::make_unique(); if (node->matches("?origin", 1, 1)) return std::make_unique(aWord(node->arguments[0])); + if (node->matches("?phasing", 0, 0)) + return std::make_unique(file); if (node->matches("?section", 1, 1)) return std::make_unique(aWord(node->arguments[0])); if (node->matches("?source-package", 1, 1)) diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 2d48a1cc9..5fc00377f 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -243,6 +243,16 @@ struct APT_HIDDEN PackageIsObsolete : public PackageMatcher } }; +struct APT_HIDDEN PackageIsPhasing : public PackageMatcher +{ + pkgCacheFile *Cache; + explicit PackageIsPhasing(pkgCacheFile *Cache) : Cache(Cache) {} + bool operator()(pkgCache::PkgIterator const &pkg) override + { + return (*Cache)->PhasingApplied(pkg); + } +}; + struct APT_HIDDEN PackageIsUpgradable : public PackageMatcher { pkgCacheFile *Cache; diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 6b3f91e96..e69854e6d 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -116,6 +116,9 @@ ?obsolete~o Selects packages that no longer exist in repositories. + ?phasing + Selects packages that will be kept back in upgrades due to phasing. + ?upgradable~U Selects packages that can be upgraded (have a newer candidate). diff --git a/test/integration/test-phased-updates-upgrade b/test/integration/test-phased-updates-upgrade index 2f5327f05..518e39fed 100755 --- a/test/integration/test-phased-updates-upgrade +++ b/test/integration/test-phased-updates-upgrade @@ -67,6 +67,11 @@ Conf depends-phased-new (3 unstable-updates [all]) Conf phased-security (3 unstable-updates [all]) Conf phased-security-same (3 unstable-security, unstable-updates [all])" aptget dist-upgrade -s -q +testsuccessequal "Listing... +phased-dep/unstable-updates 3 all [upgradable from: 1] +phased-depends-ready-dep/unstable-updates 3 all [upgradable from: 1] +phased/unstable-updates 3 all [upgradable from: 1]" apt list '?phasing' + for always in APT::Get::Always-Include-Phased-Updates Update-Manager::Always-Include-Phased-Updates; do testsuccessequal "Reading package lists... Building dependency tree... -- cgit v1.2.3-70-g09d2 From 82f4cfc971ef6a2e56b34227d9e0b1a594dc2265 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 13 Feb 2024 12:33:51 +0100 Subject: Add the ?security pattern --- apt-pkg/cachefilter-patterns.cc | 2 ++ apt-pkg/cachefilter-patterns.h | 9 +++++++++ doc/apt-patterns.7.xml | 3 +++ test/integration/test-phased-updates-upgrade | 4 ++++ 4 files changed, 18 insertions(+) diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index 6ef34c953..7e6d84ff6 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -502,6 +502,8 @@ std::unique_ptr PatternParser::aPattern(std::unique_p return std::make_unique(file); if (node->matches("?section", 1, 1)) return std::make_unique(aWord(node->arguments[0])); + if (node->matches("?security", 0, 0)) + return std::make_unique(); if (node->matches("?source-package", 1, 1)) return std::make_unique(aWord(node->arguments[0])); if (node->matches("?source-version", 1, 1)) diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 5fc00377f..fa4605253 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -415,6 +415,15 @@ struct APT_HIDDEN VersionIsSection : public VersionAnyMatcher } }; +struct APT_HIDDEN VersionIsSecurity : public VersionAnyMatcher +{ + VersionIsSecurity() {} + bool operator()(pkgCache::VerIterator const &Ver) override + { + return Ver.IsSecurityUpdate(); + } +}; + struct APT_HIDDEN VersionIsSourcePackage : public VersionAnyMatcher { BaseRegexMatcher matcher; diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index e69854e6d..e87fef23d 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -162,6 +162,9 @@ ?priority(NAME)~pNAME Selects versions where the Priority string equals the given name. + ?security + Selects packages that are a security update or succeed a security update. + diff --git a/test/integration/test-phased-updates-upgrade b/test/integration/test-phased-updates-upgrade index 518e39fed..3bee1dc86 100755 --- a/test/integration/test-phased-updates-upgrade +++ b/test/integration/test-phased-updates-upgrade @@ -72,6 +72,10 @@ phased-dep/unstable-updates 3 all [upgradable from: 1] phased-depends-ready-dep/unstable-updates 3 all [upgradable from: 1] phased/unstable-updates 3 all [upgradable from: 1]" apt list '?phasing' +testsuccessequal "Listing... +phased-security-same/unstable-security,unstable-updates 3 all [upgradable from: 1] +phased-security/unstable-updates 3 all [upgradable from: 1]" apt list '?security' + for always in APT::Get::Always-Include-Phased-Updates Update-Manager::Always-Include-Phased-Updates; do testsuccessequal "Reading package lists... Building dependency tree... -- cgit v1.2.3-70-g09d2 From 1a0882558da05eaf471c2b4049ae27305e7c70ec Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 13 Feb 2024 12:54:07 +0100 Subject: Show a separate list of upgrades deferred due to phasing This introduces a new line: The following upgrades have been deferred due to phasing This is any kept back package that is also phasing. This may not be 100% accurate as we have kept it back due to other reasons in an install command, for example, but we don't track for which packages we applied phasing in reality. If additional packages are kept back that are not phasing, show a a notice "N: Some packages may have been kept back due to phasing." LP: #1988819 --- apt-private/private-install.cc | 17 ++++++++- apt-private/private-output.cc | 10 ++++++ apt-private/private-output.h | 1 + test/integration/test-phased-updates-new-depends | 6 ++-- test/integration/test-phased-updates-upgrade | 42 ++++++++++++++++++---- .../test-ubuntu-bug-2025462-phased-dist-upgrade | 4 ++- 6 files changed, 68 insertions(+), 12 deletions(-) diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 2f254ca27..dbcba8fd1 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -210,11 +210,26 @@ bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, boo return false; } + APT::PackageVector PhasingPackages; + APT::PackageVector NotPhasingHeldBackPackages; + for (auto const &Pkg : HeldBackPackages) + { + if (Cache->PhasingApplied(Pkg)) + PhasingPackages.push_back(Pkg); + else + NotPhasingHeldBackPackages.push_back(Pkg); + } + // Show all the various warning indicators ShowDel(c1out,Cache); ShowNew(c1out,Cache); if (ShwKept == true) - ShowKept(c1out,Cache, HeldBackPackages); + { + ShowPhasing(c1out, Cache, PhasingPackages); + ShowKept(c1out, Cache, NotPhasingHeldBackPackages); + if (not PhasingPackages.empty() && not NotPhasingHeldBackPackages.empty()) + _error->Notice("Some packages may have been kept back due to phasing."); + } bool const Hold = not ShowHold(c1out,Cache); if (_config->FindB("APT::Get::Show-Upgraded",true) == true) ShowUpgraded(c1out,Cache); diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 03fbe47e1..c73d5229b 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -490,6 +490,16 @@ void ShowDel(ostream &out,CacheFile &Cache) CandidateVersion(&Cache)); } /*}}}*/ +// ShowPhasing - Show packages kept due to phasing /*{{{*/ +void ShowPhasing(ostream &out, CacheFile &Cache, APT::PackageVector const &HeldBackPackages) +{ + SortedPackageUniverse Universe(Cache); + ShowList(out, _("The following upgrades have been deferred due to phasing:"), HeldBackPackages, + &AlwaysTrue, + &PrettyFullName, + CurrentToCandidateVersion(&Cache)); +} + /*}}}*/ // ShowKept - Show kept packages /*{{{*/ void ShowKept(ostream &out,CacheFile &Cache, APT::PackageVector const &HeldBackPackages) { diff --git a/apt-private/private-output.h b/apt-private/private-output.h index d6f25e1ec..c3e73d592 100644 --- a/apt-private/private-output.h +++ b/apt-private/private-output.h @@ -93,6 +93,7 @@ template bool void ShowNew(std::ostream &out,CacheFile &Cache); void ShowDel(std::ostream &out,CacheFile &Cache); void ShowKept(std::ostream &out,CacheFile &Cache, APT::PackageVector const &HeldBackPackages); +void ShowPhasing(std::ostream &out, CacheFile &Cache, APT::PackageVector const &HeldBackPackages); void ShowUpgraded(std::ostream &out,CacheFile &Cache); bool ShowDowngraded(std::ostream &out,CacheFile &Cache); bool ShowHold(std::ostream &out,CacheFile &Cache); diff --git a/test/integration/test-phased-updates-new-depends b/test/integration/test-phased-updates-new-depends index 8cc9314ad..5d6ac80d8 100755 --- a/test/integration/test-phased-updates-new-depends +++ b/test/integration/test-phased-updates-new-depends @@ -35,7 +35,7 @@ The following packages have been kept back: testsuccessequal "Reading package lists... Building dependency tree... Calculating upgrade... -The following packages have been kept back: +The following upgrades have been deferred due to phasing: has-new-conflicts has-new-depends has-new-recommends 0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded." aptget upgrade -s -q @@ -62,7 +62,7 @@ Conf new-recommends (2 unstable-updates [all])" aptget upgrade -s -q --with-new- testsuccessequal "Reading package lists... Building dependency tree... Calculating upgrade... -The following packages have been kept back: +The following upgrades have been deferred due to phasing: has-new-conflicts has-new-depends has-new-recommends 0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded." aptget upgrade -s -q --with-new-pkgs @@ -91,6 +91,6 @@ Conf new-recommends (2 unstable-updates [all])" aptget dist-upgrade -s -q -o APT testsuccessequal "Reading package lists... Building dependency tree... Calculating upgrade... -The following packages have been kept back: +The following upgrades have been deferred due to phasing: has-new-conflicts has-new-depends has-new-recommends 0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded." aptget dist-upgrade -s -q diff --git a/test/integration/test-phased-updates-upgrade b/test/integration/test-phased-updates-upgrade index 3bee1dc86..4f415f22e 100755 --- a/test/integration/test-phased-updates-upgrade +++ b/test/integration/test-phased-updates-upgrade @@ -53,8 +53,10 @@ Building dependency tree... Calculating upgrade... The following NEW packages will be installed: phased-new +The following upgrades have been deferred due to phasing: + phased phased-dep phased-depends-ready-dep The following packages have been kept back: - depends-phased-dep phased phased-dep phased-depends-ready-dep ready-dep + depends-phased-dep ready-dep The following packages will be upgraded: depends-phased-new phased-security phased-security-same 3 upgraded, 1 newly installed, 0 to remove and 5 not upgraded. @@ -67,6 +69,23 @@ Conf depends-phased-new (3 unstable-updates [all]) Conf phased-security (3 unstable-updates [all]) Conf phased-security-same (3 unstable-security, unstable-updates [all])" aptget dist-upgrade -s -q +testequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following upgrades have been deferred due to phasing: + phased phased-dep phased-depends-ready-dep +The following packages have been kept back: + depends-phased-dep ready-dep +The following packages will be upgraded: + depends-phased-new phased-security phased-security-same +3 upgraded, 1 newly installed, 0 to remove and 5 not upgraded. +Need to get 0 B/168 B of archives. +After this operation, 43.0 kB of additional disk space will be used. +N: Some packages may have been kept back due to phasing. +Do you want to continue? [Y/n] Abort." apt dist-upgrade < /dev/null + testsuccessequal "Listing... phased-dep/unstable-updates 3 all [upgradable from: 1] phased-depends-ready-dep/unstable-updates 3 all [upgradable from: 1] @@ -140,8 +159,10 @@ Building dependency tree... Calculating upgrade... The following NEW packages will be installed: phased-new +The following upgrades have been deferred due to phasing: + phased phased-dep phased-depends-ready-dep The following packages have been kept back: - depends-phased-dep phased phased-dep phased-depends-ready-dep ready-dep + depends-phased-dep ready-dep The following packages will be upgraded: depends-phased-new phased-security phased-security-same 3 upgraded, 1 newly installed, 0 to remove and 5 not upgraded. @@ -160,8 +181,10 @@ Building dependency tree... Calculating upgrade... The following NEW packages will be installed: phased-new +The following upgrades have been deferred due to phasing: + phased phased-dep phased-depends-ready-dep The following packages have been kept back: - depends-phased-dep phased phased-dep phased-depends-ready-dep ready-dep + depends-phased-dep ready-dep The following packages will be upgraded: depends-phased-new phased-security phased-security-same 3 upgraded, 1 newly installed, 0 to remove and 5 not upgraded. @@ -177,9 +200,10 @@ Conf phased-security-same (3 unstable-security, unstable-updates [all])" aptget testsuccessequal "Reading package lists... Building dependency tree... Calculating upgrade... +The following upgrades have been deferred due to phasing: + phased phased-dep phased-depends-ready-dep The following packages have been kept back: - depends-phased-dep depends-phased-new phased phased-dep - phased-depends-ready-dep ready-dep + depends-phased-dep depends-phased-new ready-dep The following packages will be upgraded: phased-security phased-security-same 2 upgraded, 0 newly installed, 0 to remove and 6 not upgraded. @@ -194,8 +218,10 @@ Building dependency tree... Calculating upgrade... The following NEW packages will be installed: phased-new +The following upgrades have been deferred due to phasing: + phased phased-depends-ready-dep The following packages have been kept back: - phased phased-depends-ready-dep ready-dep + ready-dep The following packages will be upgraded: depends-phased-dep depends-phased-new phased-dep phased-security phased-security-same @@ -217,8 +243,10 @@ done testsuccessequal "Reading package lists... Building dependency tree... Calculating upgrade... +The following upgrades have been deferred due to phasing: + phased phased-depends-ready-dep The following packages have been kept back: - depends-phased-new phased phased-depends-ready-dep ready-dep + depends-phased-new ready-dep The following packages will be upgraded: depends-phased-dep phased-dep phased-security phased-security-same 4 upgraded, 0 newly installed, 0 to remove and 4 not upgraded. diff --git a/test/integration/test-ubuntu-bug-2025462-phased-dist-upgrade b/test/integration/test-ubuntu-bug-2025462-phased-dist-upgrade index eecadcda3..567864230 100755 --- a/test/integration/test-ubuntu-bug-2025462-phased-dist-upgrade +++ b/test/integration/test-ubuntu-bug-2025462-phased-dist-upgrade @@ -32,8 +32,10 @@ setupaptarchive testsuccessequal "Reading package lists... Building dependency tree... Calculating upgrade... +The following upgrades have been deferred due to phasing: + mutter The following packages have been kept back: - gnome-shell gnome-shell-common mutter + gnome-shell gnome-shell-common 0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded." aptget dist-upgrade -s -q testsuccessequal "Reading package lists... -- cgit v1.2.3-70-g09d2