summaryrefslogtreecommitdiff
path: root/apt-pkg/depcache.cc
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2020-04-27 13:49:19 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2020-04-27 13:49:19 +0200
commitf76a8d331a81bc7b102bdd4e0f8363e8a59f64f6 (patch)
treeb89adccf5e9cfc80d72cd64113dcb73803f99534 /apt-pkg/depcache.cc
parent347ea3f76ab263c729468e07b910ae027b66c9d8 (diff)
Propagate Protected flag to single-option dependencies
If a package is protected and has a dependency satisfied only by a single package (or conflicts with a package) this package must be part of the solution and so we can help later actions not exploring dead ends by propagating the protected flag to these "pseudo-protected" packages. An (obscure) bug this can help prevent (to some extend) is shown in test-apt-never-markauto-sections by not causing irreversible autobit transfers. As a sideeffect it seems also to help our crude ShowBroken to display slightly more helpful messages involving the packages which are actually in conflict.
Diffstat (limited to 'apt-pkg/depcache.cc')
-rw-r--r--apt-pkg/depcache.cc24
1 files changed, 20 insertions, 4 deletions
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 4b2da4b4b..03fc58f69 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -1170,6 +1170,8 @@ bool pkgDepCache::MarkInstall_RemoveConflictsIfNotUpgradeable(pkgCache::VerItera
std::clog << OutputInDepth(Depth) << " Removing: " << Pkg.Name() << " as upgrade is not an option for " << PV.ParentPkg().FullName() << "(" << PV.VerStr() << ")\n";
if (not MarkDelete(Pkg, false, Depth + 1, false))
return false;
+ if (PkgState[PV.ParentPkg()->ID].Protect())
+ MarkProtected(Pkg);
}
}
}
@@ -1177,7 +1179,7 @@ bool pkgDepCache::MarkInstall_RemoveConflictsIfNotUpgradeable(pkgCache::VerItera
return true;
}
/*}}}*/
-bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade) /*{{{*/
+bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade) /*{{{*/
{
for (auto const &InstPkg : toUpgrade)
if (not MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps))
@@ -1186,6 +1188,8 @@ bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(unsigned long Depth, bool
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())
+ MarkProtected(InstPkg);
}
toUpgrade.clear();
return true;
@@ -1200,6 +1204,7 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign
Dep.GlobOr(Start, End);
if (std::any_of(Start, Dep, IsSatisfiedByInstalled))
continue;
+ bool const IsCriticalDep = Start.IsCritical();
/* Check if any ImportantDep() (but not Critical) were added
* since we installed the package. Also check for deps that
@@ -1208,7 +1213,7 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign
* package should follow that Recommends rather than causing the
* dependency to be removed. (bug #470115)
*/
- if (Pkg->CurrentVer != 0 && not ForceImportantDeps && not Start.IsCritical())
+ if (Pkg->CurrentVer != 0 && not ForceImportantDeps && not IsCriticalDep)
{
bool isNewImportantDep = true;
bool isPreviouslySatisfiedImportantDep = false;
@@ -1253,6 +1258,7 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign
}
bool foundSolution = false;
+ bool thereIsOnlyOne1 = Start == End;
do
{
if ((DepState[Start->ID] & DepCVer) != DepCVer)
@@ -1261,6 +1267,7 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign
pkgCacheFile CacheFile(this);
APT::VersionList verlist = APT::VersionList::FromDependency(CacheFile, Start, APT::CacheSetHelper::CANDIDATE);
CompareProviders comp(Start);
+ bool thereIsOnlyOne2 = thereIsOnlyOne1 && verlist.size() == 1;
do
{
@@ -1272,6 +1279,15 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign
if (DebugAutoInstall)
std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name()
<< " as " << Start.DepType() << " of " << Pkg.Name() << '\n';
+ if (thereIsOnlyOne2 && PkgState[Pkg->ID].Protect() && IsCriticalDep)
+ {
+ if (not MarkInstall(InstPkg, false, Depth + 1, false, ForceImportantDeps))
+ {
+ verlist.erase(InstVer);
+ continue;
+ }
+ MarkProtected(InstPkg);
+ }
if (not MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps))
{
verlist.erase(InstVer);
@@ -1287,7 +1303,7 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign
if (foundSolution)
break;
} while (Start++ != End);
- if (not foundSolution && End.IsCritical())
+ if (not foundSolution && IsCriticalDep)
{
StateCache &State = PkgState[Pkg->ID];
if (not State.Protect())
@@ -1366,7 +1382,7 @@ 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(Depth, ForceImportantDeps, toUpgrade))
+ if (not MarkInstall_UpgradeOrRemoveConflicts(Pkg, Depth, ForceImportantDeps, toUpgrade))
return false;
bool const MoveAutoBitToDependencies = [&]() {