summaryrefslogtreecommitdiff
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
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.
-rw-r--r--apt-pkg/depcache.cc24
-rw-r--r--apt-pkg/depcache.h2
-rwxr-xr-xtest/integration/test-apt-never-markauto-sections11
-rwxr-xr-xtest/integration/test-bug-604222-new-and-autoremove3
-rwxr-xr-xtest/integration/test-bug-735967-lib32-to-i386-unavailable4
-rwxr-xr-xtest/integration/test-explore-or-groups-in-markinstall4
-rwxr-xr-xtest/integration/test-multiarch-allowed11
7 files changed, 38 insertions, 21 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 = [&]() {
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
index 669514e3f..339686b95 100644
--- a/apt-pkg/depcache.h
+++ b/apt-pkg/depcache.h
@@ -521,7 +521,7 @@ 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(unsigned long Depth, bool const ForceImportantDeps, 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);
};
diff --git a/test/integration/test-apt-never-markauto-sections b/test/integration/test-apt-never-markauto-sections
index aa145d217..6ad89c506 100755
--- a/test/integration/test-apt-never-markauto-sections
+++ b/test/integration/test-apt-never-markauto-sections
@@ -27,7 +27,7 @@ testsuccess aptcache show nosection
testfailure grep 'Section' rootdir/tmp/testsuccess.output
testequal 'dpkg' aptmark showmanual
-testsuccess aptget install mydesktop -y -o Debug::pkgProblemResolver=1 -o Debug::pkgDepCache::Marker=1
+testsuccess aptget install mydesktop -y -o Debug::pkgProblemResolver=1 -o Debug::pkgDepCache::Marker=1 -o Debug::pkgDepCache::AutoInstall=1
testmarkedmanual 'dpkg' 'mydesktop'
testmarkedauto 'mydesktop-core' 'foreignpkg:i386' 'texteditor' 'browser' 'nosection'
@@ -75,12 +75,7 @@ testsuccess aptmark auto nosection
testmarkedauto 'browser' 'nosection'
testmarkedmanual 'dpkg' 'foreignpkg:i386'
-# nosection should be auto, not manual, but is marked as such by the resolver
-# removing mydesktop-core temporally… the resolver should be figuring out here
-# that there is no point of removing mydesktop-core as its an unavoidable
-# dependency of the user-requested mydesktop
-
testsuccess aptget install mydesktop -y -o Debug::pkgProblemResolver=1 -o Debug::pkgDepCache::Marker=1 -o Debug::pkgDepCache::AutoInstall=1
-testmarkedmanual 'dpkg' 'foreignpkg:i386' 'mydesktop' 'nosection'
-testmarkedauto 'browser' 'mydesktop-core' 'texteditor'
+testmarkedmanual 'dpkg' 'foreignpkg:i386' 'mydesktop'
+testmarkedauto 'browser' 'mydesktop-core' 'texteditor' 'nosection'
diff --git a/test/integration/test-bug-604222-new-and-autoremove b/test/integration/test-bug-604222-new-and-autoremove
index b8faf4fe6..6009ca0d2 100755
--- a/test/integration/test-bug-604222-new-and-autoremove
+++ b/test/integration/test-bug-604222-new-and-autoremove
@@ -88,12 +88,13 @@ rm -f rootdir/var/lib/apt/extended_states
CONFLICTING='Reading package lists...
Building dependency tree...
MarkInstall dummy-archive:i386 < none -> 0.invalid.0 @un puN Ib > FU=1
- MarkInstall libavcodec52:i386 < none -> 4:0.5.2-6 @un uN > FU=0
MarkInstall libvtk5-dev:i386 < none -> 5.4.2-8 @un uN Ib > FU=0
MarkInstall libvtk5.4:i386 < none -> 5.4.2-8 @un uN > FU=0
MarkKeep libvtk5-dev:i386 < none -> 5.4.2-8 @un uN > FU=0
MarkKeep libvtk5-dev:i386 < none -> 5.4.2-8 @un uN > FU=0
+ Ignore MarkGarbage of libavcodec52:i386 < none -> 4:0.5.2-6 @un puN > as its mode (Install) is protected
MarkDelete libvtk5.4:i386 < none -> 5.4.2-8 @un ugN > FU=0
+ Ignore MarkGarbage of libavcodec52:i386 < none -> 4:0.5.2-6 @un puN > as its mode (Install) is protected
The following additional packages will be installed:
libavcodec52 libopenal-dev
The following NEW packages will be installed:
diff --git a/test/integration/test-bug-735967-lib32-to-i386-unavailable b/test/integration/test-bug-735967-lib32-to-i386-unavailable
index 16aee4340..9dbd17bfd 100755
--- a/test/integration/test-bug-735967-lib32-to-i386-unavailable
+++ b/test/integration/test-bug-735967-lib32-to-i386-unavailable
@@ -52,8 +52,8 @@ or been moved out of Incoming.
The following information may help to resolve the situation:
The following packages have unmet dependencies:
- foo : Depends: libfoo but it is not installable
-E: Unable to correct problems, you have held broken packages.' aptget install foo -s
+ libfoo : Depends: libfoo-bin but it is not installable
+E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.' aptget install foo -s
# activate multiarch
configarchitecture 'amd64' 'i386'
diff --git a/test/integration/test-explore-or-groups-in-markinstall b/test/integration/test-explore-or-groups-in-markinstall
index f5898cfca..db97574bb 100755
--- a/test/integration/test-explore-or-groups-in-markinstall
+++ b/test/integration/test-explore-or-groups-in-markinstall
@@ -11,10 +11,12 @@ insertpackage 'unstable' 'unneeded' 'all' '1'
insertpackage 'unstable' 'later' 'all' '1'
insertpackage 'unstable' 'bad-level0' 'all' '1' 'Depends: unneeded, unknown'
+insertpackage 'unstable' 'bad-level1' 'all' '1' 'Depends: bad-level0'
insertfoos() {
insertpackage 'unstable' "foo-${1}-level0" 'all' '1' "${2}: unknown | okay | later"
insertpackage 'unstable' "foo-${1}-level1" 'all' '1' "${2}: bad-level0 | okay | later"
+ insertpackage 'unstable' "foo-${1}-level2" 'all' '1' "${2}: bad-level1 | okay | later"
}
insertfoos 'd' 'Depends'
insertfoos 'r' 'Recommends'
@@ -33,7 +35,7 @@ testsuccessheadequal() {
}
checkfoos() {
msgmsg 'Install checks with foos dependency type' "$2"
- for i in 0 1; do
+ for i in 0 1 2; do
testsuccessheadequal 7 "Reading package lists...
Building dependency tree...
The following additional packages will be installed:
diff --git a/test/integration/test-multiarch-allowed b/test/integration/test-multiarch-allowed
index 98555bc73..b74853993 100755
--- a/test/integration/test-multiarch-allowed
+++ b/test/integration/test-multiarch-allowed
@@ -64,12 +64,15 @@ Conf foo:i386 (1 unstable [i386])
Conf needsfoo:i386 (1 unstable [i386])' aptget install needsfoo:i386 -s
testfailureequal "$BADPREFIX
The following packages have unmet dependencies:
- needsfoo:i386 : Depends: foo:i386 but it is not going to be installed
-E: Unable to correct problems, you have held broken packages." aptget install needsfoo:i386 foo:amd64 -s
+ foo : Conflicts: foo:i386 but 1 is to be installed
+ foo:i386 : Conflicts: foo but 1 is to be installed
+E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages." aptget install needsfoo:i386 foo:amd64 -s
testfailureequal "$BADPREFIX
The following packages have unmet dependencies:
- needsfoo : Depends: foo but it is not going to be installed
-E: Unable to correct problems, you have held broken packages." aptget install needsfoo foo:i386 -s
+ foo : Conflicts: foo:i386 but 1 is to be installed
+ foo:i386 : Conflicts: foo but 1 is to be installed
+E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages." aptget install needsfoo foo:i386 -s
+exit
solveableinsinglearch1() {
testsuccessequal "Reading package lists...