summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2020-04-27 13:51:46 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2020-04-27 13:51:46 +0200
commitae23e53f99ea0b7920744a7303fdee64796b7cce (patch)
tree6201c01507e3db1e897918f3b8a03701bbca708f
parentca14e1e2c3f3c9782f374757ca4605ce7e5670ad (diff)
Protect a package while resolving in MarkInstall
Strange things happen if while resolving the dependencies of a package said dependencies want to remove the package. The allow-scores test e.g. removed the preferred alternative in favor of the last one now that they were exclusive. In our or-group for Recommends we would "just" not statisfy the Recommends and for Depends we engage the ProblemResolver…
-rw-r--r--apt-pkg/depcache.cc35
-rw-r--r--apt-pkg/depcache.h4
-rwxr-xr-xtest/integration/test-allow-scores-for-all-dependency-types34
-rwxr-xr-xtest/integration/test-explore-or-groups-in-markinstall14
4 files changed, 48 insertions, 39 deletions
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 2254a9b5d..7730aaf5b 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -1180,7 +1180,7 @@ bool pkgDepCache::MarkInstall_RemoveConflictsIfNotUpgradeable(pkgCache::VerItera
return true;
}
/*}}}*/
-bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade) /*{{{*/
+bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(bool const propagateProctected, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade) /*{{{*/
{
for (auto const &InstPkg : toUpgrade)
if (not MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps))
@@ -1189,14 +1189,14 @@ bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(PkgIterator const &Pkg, u
std::clog << OutputInDepth(Depth) << " Removing: " << InstPkg.FullName() << " as upgrade is not possible\n";
if (not MarkDelete(InstPkg, false, Depth + 1, false))
return false;
- if (PkgState[Pkg->ID].Protect())
+ if (propagateProctected)
MarkProtected(InstPkg);
}
toUpgrade.clear();
return true;
}
/*}}}*/
-bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto) /*{{{*/
+bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto, bool const propagateProctected) /*{{{*/
{
auto const IsSatisfiedByInstalled = [&](auto const D) { return (DepState[D.ID] & DepInstall) == DepInstall; };
for (auto &&Dep : toInstall)
@@ -1286,7 +1286,7 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign
if (DebugAutoInstall)
std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.FullName()
<< " as " << End.DepType() << " of " << Pkg.FullName() << '\n';
- if (IsCriticalDep && toUpgrade.size() == 1 && PkgState[Pkg->ID].Protect())
+ if (propagateProctected && IsCriticalDep && toUpgrade.size() == 1)
{
if (not MarkInstall(InstPkg, false, Depth + 1, false, ForceImportantDeps))
continue;
@@ -1303,9 +1303,9 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign
}
if (not foundSolution && IsCriticalDep)
{
- StateCache &State = PkgState[Pkg->ID];
- if (not State.Protect())
+ if (not propagateProctected)
{
+ StateCache &State = PkgState[Pkg->ID];
RemoveSizes(Pkg);
RemoveStates(Pkg);
if (Pkg->CurrentVer != 0)
@@ -1380,7 +1380,26 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst,
if (DebugMarker)
std::clog << OutputInDepth(Depth) << "MarkInstall " << APT::PrettyPkg(this, Pkg) << " FU=" << FromUser << '\n';
- if (not MarkInstall_UpgradeOrRemoveConflicts(Pkg, Depth, ForceImportantDeps, toUpgrade))
+ class ScopedProtected
+ {
+ pkgDepCache::StateCache &P;
+ bool const already;
+
+ public:
+ ScopedProtected(pkgDepCache::StateCache &p) : P{p}, already{P.Protect()}
+ {
+ if (not already)
+ P.iFlags |= Protected;
+ }
+ ~ScopedProtected()
+ {
+ if (not already)
+ P.iFlags &= (~Protected);
+ }
+ operator bool() noexcept { return already; }
+ } propagateProctected{PkgState[Pkg->ID]};
+
+ if (not MarkInstall_UpgradeOrRemoveConflicts(propagateProctected, Depth, ForceImportantDeps, toUpgrade))
return false;
bool const MoveAutoBitToDependencies = [&]() {
@@ -1400,7 +1419,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst,
}();
APT::PackageVector toMoveAuto;
- if (not MarkInstall_InstallDependencies(Pkg, Depth, ForceImportantDeps, toInstall, MoveAutoBitToDependencies ? &toMoveAuto : nullptr))
+ if (not MarkInstall_InstallDependencies(Pkg, Depth, ForceImportantDeps, toInstall, MoveAutoBitToDependencies ? &toMoveAuto : nullptr, propagateProctected))
return false;
if (MoveAutoBitToDependencies)
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
index 339686b95..1579fedbe 100644
--- a/apt-pkg/depcache.h
+++ b/apt-pkg/depcache.h
@@ -521,8 +521,8 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace
APT_HIDDEN bool MarkInstall_StateChange(PkgIterator const &Pkg, bool AutoInst, bool FromUser);
APT_HIDDEN bool MarkInstall_CollectDependencies(pkgCache::VerIterator const &PV, std::vector<pkgCache::DepIterator> &toInstall, std::vector<pkgCache::DepIterator> &toRemove);
APT_HIDDEN bool MarkInstall_RemoveConflictsIfNotUpgradeable(pkgCache::VerIterator const &PV, unsigned long Depth, std::vector<pkgCache::DepIterator> &toRemove, APT::PackageVector &toUpgrade);
- APT_HIDDEN bool MarkInstall_UpgradeOrRemoveConflicts(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade);
- APT_HIDDEN bool MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto);
+ APT_HIDDEN bool MarkInstall_UpgradeOrRemoveConflicts(bool const propagateProtected, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade);
+ APT_HIDDEN bool MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto, bool const propagateProtected);
};
#endif
diff --git a/test/integration/test-allow-scores-for-all-dependency-types b/test/integration/test-allow-scores-for-all-dependency-types
index 9b300b7a7..b8a9ed3ea 100755
--- a/test/integration/test-allow-scores-for-all-dependency-types
+++ b/test/integration/test-allow-scores-for-all-dependency-types
@@ -116,42 +116,18 @@ Conf baz (2 unversioned [amd64])' aptget install baz -st unversioned
testsuccessequal 'Reading package lists...
Building dependency tree...
The following additional packages will be installed:
- foo
-The following packages will be REMOVED:
bar
-The following NEW packages will be installed:
- baz
-The following packages will be upgraded:
- foo
-1 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
-Remv bar [1]
-Inst foo [1] (2 versioned [amd64])
-Inst baz (2 versioned [amd64])
-Conf foo (2 versioned [amd64])
-Conf baz (2 versioned [amd64])' aptget install baz -st versioned
-
-testsuccessequal 'Reading package lists...
-Building dependency tree...
-The following NEW packages will be installed:
- baz
-0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded.
-Inst baz (2 unversioned [amd64])
-Conf baz (2 unversioned [amd64])' aptget install baz -st unversioned
-testsuccessequal 'Reading package lists...
-Building dependency tree...
-The following additional packages will be installed:
- foo
The following packages will be REMOVED:
- bar
+ foo
The following NEW packages will be installed:
baz
The following packages will be upgraded:
- foo
+ bar
1 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
-Remv bar [1]
-Inst foo [1] (2 versioned [amd64])
+Remv foo [1]
+Inst bar [1] (2 versioned [amd64])
Inst baz (2 versioned [amd64])
-Conf foo (2 versioned [amd64])
+Conf bar (2 versioned [amd64])
Conf baz (2 versioned [amd64])' aptget install baz -st versioned
# recreating the exact situation is hard, so we pull tricks to get the score
diff --git a/test/integration/test-explore-or-groups-in-markinstall b/test/integration/test-explore-or-groups-in-markinstall
index 259155854..5669e47b3 100755
--- a/test/integration/test-explore-or-groups-in-markinstall
+++ b/test/integration/test-explore-or-groups-in-markinstall
@@ -15,6 +15,10 @@ insertpackage 'unstable' 'bad-level0' 'all' '1' 'Depends: unneeded, unknown'
insertpackage 'unstable' 'bad-level1' 'all' '1' 'Depends: bad-level0'
insertpackage 'unstable' 'bad-upgrade-level0' 'all' '2' 'Depends: unneeded, unknown'
insertpackage 'unstable' 'bad-upgrade-level1' 'all' '2' 'Depends: bad-upgrade-level0 (>= 2)'
+insertpackage 'unstable' 'bad-conflict-level0' 'all' '1' 'Depends: unneeded
+Conflicts: bad-conflict-level2'
+insertpackage 'unstable' 'bad-conflict-level1' 'all' '1' 'Depends: bad-conflict-level0'
+insertpackage 'unstable' 'bad-conflict-level2' 'all' '1' 'Depends: bad-conflict-level1'
insertinstalledpackage 'upgrade' 'all' '1'
insertinstalledpackage 'bad-upgrade' 'all' '1'
@@ -29,6 +33,8 @@ insertfoos() {
insertpackage 'unstable' "foo-${1}-upgrade-level0" 'all' '1' "${2}: bad-upgrade (>= 2) | okay | upgrade (>= 2) | later"
insertpackage 'unstable' "foo-${1}-upgrade-level1" 'all' '1' "${2}: bad-upgrade-level0 (>= 2) | bad-upgrade-level0 (>= 2) | bad-level0 | okay | upgrade (>= 2) | later"
insertpackage 'unstable' "foo-${1}-upgrade-level2" 'all' '1' "${2}: bad-upgrade-level1 (>= 2) | bad-upgrade-level1 (>= 2) | bad-level1 | okay | upgrade (>= 2) | later"
+
+ insertpackage 'unstable' "foo-${1}-conflict" 'all' '1' "${2}: unknown | bad-conflict-level2 | okay | later"
}
insertfoos 'd' 'Depends'
insertfoos 'r' 'Recommends'
@@ -65,6 +71,14 @@ The following packages will be upgraded:
upgrade
1 upgraded, 1 newly installed, 0 to remove and $((2-${level})) not upgraded." apt install foo-${1}-upgrade-level${level} -s
done
+
+ testsuccessheadequal 7 "Reading package lists...
+Building dependency tree...
+The following additional packages will be installed:
+ okay
+The following NEW packages will be installed:
+ foo-${1}-conflict okay
+0 upgraded, 2 newly installed, 0 to remove and 3 not upgraded." apt install foo-${1}-conflict -s
}
checkfoos 'd' 'Depends'
checkfoos 'r' 'Recommends'