diff options
author | Julian Andres Klode <jak@debian.org> | 2022-06-29 13:30:03 +0000 |
---|---|---|
committer | Julian Andres Klode <jak@debian.org> | 2022-06-29 13:30:03 +0000 |
commit | e4230878687c6d9bd3b13552bb2c1053b9d7d7d8 (patch) | |
tree | 6f1583b7198ce4c8f2e8a66936f53186857f2caf | |
parent | edffb0ae26935d948ffeb3be229fdcf37d2a1ee1 (diff) | |
parent | 20739359fa936c0851a4c0f37667526d98c22761 (diff) |
Merge branch 'pu/phasing-better' into 'main'
Rewrite phased updates using a keep-back approach
See merge request apt-team/apt!245
-rw-r--r-- | apt-pkg/policy.cc | 21 | ||||
-rw-r--r-- | apt-pkg/upgrade.cc | 114 | ||||
-rw-r--r-- | doc/examples/configure-index | 1 | ||||
-rwxr-xr-x | test/integration/test-phased-updates | 28 | ||||
-rwxr-xr-x | test/integration/test-phased-updates-upgrade | 256 |
5 files changed, 410 insertions, 10 deletions
diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index b30eddb37..5fcc11b66 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -288,6 +288,13 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, // Returns true if this update is excluded by phasing. static inline bool ExcludePhased(std::string machineID, pkgCache::VerIterator const &Ver) { + if (Ver.PhasedUpdatePercentage() == 100) + return false; + + // FIXME: We have migrated to a legacy implementation until LP: #1929082 is fixed + if (not _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", @@ -312,11 +319,9 @@ static inline bool ExcludePhased(std::string machineID, pkgCache::VerIterator co } APT_PURE signed short pkgPolicy::GetPriority(pkgCache::VerIterator const &Ver, bool ConsiderFiles) { - if (Ver.PhasedUpdatePercentage() != 100) - { - if (ExcludePhased(d->machineID, Ver)) - return 1; - } + auto ceiling = std::numeric_limits<signed int>::max(); + if (ExcludePhased(d->machineID, Ver)) + ceiling = 1; if (VerPins[Ver->ID].Type != pkgVersionMatch::None) { // If all sources are never pins, the never pin wins. @@ -324,10 +329,10 @@ APT_PURE signed short pkgPolicy::GetPriority(pkgCache::VerIterator const &Ver, b return NEVER_PIN; for (pkgCache::VerFileIterator file = Ver.FileList(); file.end() == false; file++) if (GetPriority(file.File()) != NEVER_PIN) - return VerPins[Ver->ID].Priority; + return std::min((int)VerPins[Ver->ID].Priority, ceiling); } if (!ConsiderFiles) - return 0; + return std::min(0, ceiling); // priorities are short ints, but we want to pick a value outside the valid range here auto priority = std::numeric_limits<signed int>::min(); @@ -344,7 +349,7 @@ APT_PURE signed short pkgPolicy::GetPriority(pkgCache::VerIterator const &Ver, b priority = std::max<decltype(priority)>(priority, GetPriority(file.File())); } - return priority == std::numeric_limits<decltype(priority)>::min() ? 0 : priority; + return std::min(priority == std::numeric_limits<decltype(priority)>::min() ? 0 : priority, ceiling); } APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &File) { diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc index 06c3751e0..a7e18026b 100644 --- a/apt-pkg/upgrade.cc +++ b/apt-pkg/upgrade.cc @@ -2,19 +2,117 @@ #include <config.h> #include <apt-pkg/algorithms.h> +#include <apt-pkg/aptconfiguration.h> #include <apt-pkg/configuration.h> #include <apt-pkg/depcache.h> #include <apt-pkg/edsp.h> #include <apt-pkg/error.h> #include <apt-pkg/pkgcache.h> #include <apt-pkg/progress.h> +#include <apt-pkg/strutl.h> #include <apt-pkg/upgrade.h> +#include <random> #include <string> #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; + ++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].InstallVer == 0) + return false; + if (Cache[Pkg].InstVerIter(Cache).PhasedUpdatePercentage() == 100) + return false; + if (IsSecurityUpdate(Cache[Pkg].InstVerIter(Cache))) + return false; + if (!IsIgnoredPhasedUpdate(Cache[Pkg].InstVerIter(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); + if (Fix != nullptr) + Fix->Protect(I); + } + } +}; + // DistUpgrade - Distribution upgrade /*{{{*/ // --------------------------------------------------------------------- /* This autoinstalls every package and then force installs every @@ -115,6 +213,8 @@ static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress) } } + PhasedUpgrader().HoldBackIgnoredPhasedUpdates(Cache, &Fix); + bool const success = Fix.ResolveInternal(false); if (Progress != NULL) Progress->Done(); @@ -134,7 +234,7 @@ 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) { @@ -144,7 +244,10 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Pr if (_config->FindB("APT::Ignore-Hold",false) == false) if (I->SelectedState == pkgCache::State::Hold) continue; - + + if (phasedUpgrader.ShouldKeep(Cache, I)) + continue; + if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) Cache.MarkInstall(I, false, 0, false); } @@ -152,6 +255,8 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Pr if (Progress != NULL) Progress->Progress(50); + phasedUpgrader.HoldBackIgnoredPhasedUpdates(Cache, &Fix); + // resolve remaining issues via keep bool const success = Fix.ResolveByKeepInternal(); if (Progress != NULL) @@ -178,6 +283,7 @@ 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 @@ -188,6 +294,8 @@ 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)) + continue; Cache.MarkInstall(I, false, 0, false); } @@ -212,6 +320,8 @@ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const if (Progress != NULL) Progress->Progress(60); + phasedUpgrader.HoldBackIgnoredPhasedUpdates(Cache, &Fix); + // resolve remaining issues via keep bool const success = Fix.ResolveByKeepInternal(); if (Progress != NULL) diff --git a/doc/examples/configure-index b/doc/examples/configure-index index ce51153c3..07feea4dc 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -105,6 +105,7 @@ APT Upgrade-Allow-New "<BOOL>"; Always-Include-Phased-Updates "<BOOL>"; Never-Include-Phased-Updates "<BOOL>"; + Phase-Policy "<BOOL>"; // internal Purge "<BOOL>"; ReInstall "<BOOL>"; Compile "<BOOL>"; diff --git a/test/integration/test-phased-updates b/test/integration/test-phased-updates index c06d6f5a1..7377f910f 100755 --- a/test/integration/test-phased-updates +++ b/test/integration/test-phased-updates @@ -6,6 +6,7 @@ TESTDIR="$(readlink -f "$(dirname "$0")")" setupenvironment echo 'Debug::Phasing "1";' > rootdir/etc/apt/apt.conf.d/debug-phasing +echo 'APT::Get::Phase-Policy "1";' > rootdir/etc/apt/apt.conf.d/debug-phasing configarchitecture 'i386' 'armel' @@ -24,6 +25,16 @@ insertpackage 'unstable' 'phased1' 'all' '50' 'Phased-Update-Percentage: 50' insertpackage 'unstable' 'phased2' 'all' '50' 'Phased-Update-Percentage: 50' insertpackage 'unstable' 'phased3' 'all' '50' 'Phased-Update-Percentage: 50' +insertinstalledpackage 'phased-and-pinned' 'all' '1' +insertpackage 'unstable' 'phased-and-pinned' 'all' '10' 'Phased-Update-Percentage: 0' +insertpackage 'unstable' 'phased-and-pinned-new' 'all' '10' 'Phased-Update-Percentage: 0' + +cat > rootdir/etc/apt/preferences.d/phased-and-pinned << EOF +Package: phased-and-pinned phased-and-pinned-new +Pin: release * +Pin-Priority: -12 +EOF + setupaptarchive msgmsg "Basic test" @@ -62,6 +73,23 @@ phased3: 10 1 (phased 10%) 500 file:${TMPWORKINGDIRECTORY}/aptarchive unstable/main all Packages" aptcache policy phased1 phased2 phased3 +testsuccessequal "phased-and-pinned: + Installed: 1 + Candidate: (none) + Version table: + 10 -12 (phased 0%) + 500 file:${TMPWORKINGDIRECTORY}/aptarchive unstable/main all Packages + *** 1 -12 + 100 ${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status" aptcache policy phased-and-pinned + +testsuccessequal "phased-and-pinned-new: + Installed: (none) + Candidate: (none) + Version table: + 10 -12 (phased 0%) + 500 file:${TMPWORKINGDIRECTORY}/aptarchive unstable/main all Packages" aptcache policy phased-and-pinned-new + + msgmsg "Test for always-include-phased-updates" for always in Update-Manager::Always-Include-Phased-Updates APT::Get::Always-Include-Phased-Updates; do testsuccessequal "phased1: diff --git a/test/integration/test-phased-updates-upgrade b/test/integration/test-phased-updates-upgrade new file mode 100755 index 000000000..ab39681de --- /dev/null +++ b/test/integration/test-phased-updates-upgrade @@ -0,0 +1,256 @@ +#!/bin/sh +set -e + +TESTDIR="$(readlink -f "$(dirname "$0")")" +. "$TESTDIR/framework" + +setupenvironment +echo 'Debug::Phasing "1";' > rootdir/etc/apt/apt.conf.d/debug-phasing +configarchitecture 'i386' 'armel' + + + +# Test case phased: The package is installed and has a phased update available +insertinstalledpackage 'phased' 'all' '1' +insertpackage 'unstable-updates' 'phased' 'all' '3' 'Phased-Update-Percentage: 0' + +# Test case phased-security: A phased package is in security and will be installed +insertinstalledpackage 'phased-security' 'all' '1' +insertpackage 'unstable-security' 'phased-security' 'all' '2' +insertpackage 'unstable-updates' 'phased-security' 'all' '3' 'Phased-Update-Percentage: 0' + +# Test case phased-dep: A released update depends on the phased dependency phased-dep +insertinstalledpackage 'phased-dep' 'all' '1' +insertinstalledpackage 'depends-phased-dep' 'all' '1' +insertpackage 'unstable-updates' 'phased-dep' 'all' '3' 'Phased-Update-Percentage: 0' +insertpackage 'unstable-updates' 'depends-phased-dep' 'all' '3' 'Depends: phased-dep (= 3)' + +# Test case phased-new: A release update depends on a new package that's phasing +insertinstalledpackage 'depends-phased-new' 'all' '1' +insertpackage 'unstable-updates' 'phased-new' 'all' '3' 'Phased-Update-Percentage: 0' +insertpackage 'unstable-updates' 'depends-phased-new' 'all' '3' 'Depends: phased-new (= 3)' + +setupaptarchive + +msgmsg "Testing with default (upgrade-based) implementation" + +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages have been kept back: + depends-phased-dep phased phased-dep +The following packages will be upgraded: + depends-phased-new phased-security +2 upgraded, 1 newly installed, 0 to remove and 3 not upgraded. +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased-security [1] (3 unstable-updates [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased-security (3 unstable-updates [all])" aptget dist-upgrade -s -q + +for always in APT::Get::Always-Include-Phased-Updates Update-Manager::Always-Include-Phased-Updates; do +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages will be upgraded: + depends-phased-dep depends-phased-new phased phased-dep phased-security +5 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst phased-dep [1] (3 unstable-updates [all]) +Inst depends-phased-dep [1] (3 unstable-updates [all]) +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased [1] (3 unstable-updates [all]) +Inst phased-security [1] (3 unstable-updates [all]) +Conf phased-dep (3 unstable-updates [all]) +Conf depends-phased-dep (3 unstable-updates [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased (3 unstable-updates [all]) +Conf phased-security (3 unstable-updates [all])" aptget dist-upgrade -s -q -o $always=1 +done + +SOURCE_DATE_EPOCH=1 testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages will be upgraded: + depends-phased-dep depends-phased-new phased phased-dep phased-security +5 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst phased-dep [1] (3 unstable-updates [all]) +Inst depends-phased-dep [1] (3 unstable-updates [all]) +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased [1] (3 unstable-updates [all]) +Inst phased-security [1] (3 unstable-updates [all]) +Conf phased-dep (3 unstable-updates [all]) +Conf depends-phased-dep (3 unstable-updates [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased (3 unstable-updates [all]) +Conf phased-security (3 unstable-updates [all])" aptget dist-upgrade -s -q -o with-source-date-epoch=1 + +for never in APT::Get::Never-Include-Phased-Updates Update-Manager::Never-Include-Phased-Updates; do +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages have been kept back: + depends-phased-dep phased phased-dep +The following packages will be upgraded: + depends-phased-new phased-security +2 upgraded, 1 newly installed, 0 to remove and 3 not upgraded. +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased-security [1] (3 unstable-updates [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased-security (3 unstable-updates [all])" aptget dist-upgrade -s -q -o $never=1 +done + +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages have been kept back: + depends-phased-dep phased phased-dep +The following packages will be upgraded: + depends-phased-new phased-security +2 upgraded, 1 newly installed, 0 to remove and 3 not upgraded. +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased-security [1] (3 unstable-updates [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased-security (3 unstable-updates [all])" aptget upgrade -s -q --with-new-pkgs + +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following packages have been kept back: + depends-phased-dep depends-phased-new phased phased-dep +The following packages will be upgraded: + phased-security +1 upgraded, 0 newly installed, 0 to remove and 4 not upgraded. +Inst phased-security [1] (3 unstable-updates [all]) +Conf phased-security (3 unstable-updates [all])" aptget upgrade -s -q + + +msgmsg "Testing with policy based implementation" +echo 'APT::Get::Phase-Policy "1";' > rootdir/etc/apt/apt.conf.d/phase-by-policy + +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages have been kept back: + depends-phased-dep +The following packages will be upgraded: + depends-phased-new phased-security +2 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased-security [1] (2 unstable-security [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased-security (2 unstable-security [all])" aptget dist-upgrade -s -q + +for always in APT::Get::Always-Include-Phased-Updates Update-Manager::Always-Include-Phased-Updates; do +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages will be upgraded: + depends-phased-dep depends-phased-new phased phased-dep phased-security +5 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst phased-dep [1] (3 unstable-updates [all]) +Inst depends-phased-dep [1] (3 unstable-updates [all]) +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased [1] (3 unstable-updates [all]) +Inst phased-security [1] (3 unstable-updates [all]) +Conf phased-dep (3 unstable-updates [all]) +Conf depends-phased-dep (3 unstable-updates [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased (3 unstable-updates [all]) +Conf phased-security (3 unstable-updates [all])" aptget dist-upgrade -s -q -o $always=1 +done + +# In the policy implementation, we can update security +for never in APT::Get::Never-Include-Phased-Updates Update-Manager::Never-Include-Phased-Updates; do +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages have been kept back: + depends-phased-dep +The following packages will be upgraded: + depends-phased-new phased-security +2 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased-security [1] (2 unstable-security [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased-security (2 unstable-security [all])" aptget dist-upgrade -s -q -o $never=1 +done + +SOURCE_DATE_EPOCH=1 testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages will be upgraded: + depends-phased-dep depends-phased-new phased phased-dep phased-security +5 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst phased-dep [1] (3 unstable-updates [all]) +Inst depends-phased-dep [1] (3 unstable-updates [all]) +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased [1] (3 unstable-updates [all]) +Inst phased-security [1] (3 unstable-updates [all]) +Conf phased-dep (3 unstable-updates [all]) +Conf depends-phased-dep (3 unstable-updates [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased (3 unstable-updates [all]) +Conf phased-security (3 unstable-updates [all])" aptget dist-upgrade -s -q -o with-source-date-epoch=1 + +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following NEW packages will be installed: + phased-new +The following packages have been kept back: + depends-phased-dep +The following packages will be upgraded: + depends-phased-new phased-security +2 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. +Inst phased-new (3 unstable-updates [all]) +Inst depends-phased-new [1] (3 unstable-updates [all]) +Inst phased-security [1] (2 unstable-security [all]) +Conf phased-new (3 unstable-updates [all]) +Conf depends-phased-new (3 unstable-updates [all]) +Conf phased-security (2 unstable-security [all])" aptget upgrade -s -q --with-new-pkgs + +testsuccessequal "Reading package lists... +Building dependency tree... +Calculating upgrade... +The following packages have been kept back: + depends-phased-dep depends-phased-new +The following packages will be upgraded: + phased-security +1 upgraded, 0 newly installed, 0 to remove and 2 not upgraded. +Inst phased-security [1] (2 unstable-security [all]) +Conf phased-security (2 unstable-security [all])" aptget upgrade -s -q |