diff options
-rw-r--r-- | apt-pkg/depcache.cc | 39 | ||||
-rwxr-xr-x | test/integration/test-apt-get-autoremove | 36 |
2 files changed, 70 insertions, 5 deletions
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index eb8f6460d..1301cbdf9 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -12,6 +12,7 @@ #include <apt-pkg/depcache.h> #include <apt-pkg/versionmatch.h> +#include <apt-pkg/version.h> #include <apt-pkg/error.h> #include <apt-pkg/fileutl.h> #include <apt-pkg/strutl.h> @@ -1927,10 +1928,11 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &Pkg, continue; // handle the virtual part first + APT::VersionVector providers; for(auto Prv = T.ProvidesList(); Prv.end() == false; ++Prv) { auto PP = Prv.OwnerPkg(); - if (PkgState[PP->ID].Marked || IsPkgInBoringState(PP, PkgState)) + if (IsPkgInBoringState(PP, PkgState)) continue; // we want to ignore provides from uninteresting versions @@ -1939,10 +1941,37 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &Pkg, if (unlikely(PV.end()) || PV != Prv.OwnerVer() || D.IsSatisfied(Prv) == false) continue; - if (debug_autoremove) - std::clog << "Following dep: " << APT::PrettyDep(this, D) - << ", provided by " << PP.FullName() << " " << PV.VerStr() << std::endl; - MarkPackage(PP, PV, follow_recommends, follow_suggests); + providers.emplace_back(PV); + } + if (providers.empty() == false) + { + // sort providers by source version so that only the latest versioned + // binary package of a source package is marked instead of all + std::sort(providers.begin(), providers.end(), + [](pkgCache::VerIterator const &A, pkgCache::VerIterator const &B) { + auto const nameret = strcmp(A.SourcePkgName(), B.SourcePkgName()); + if (nameret != 0) + return nameret < 0; + auto const verret = A.Cache()->VS->CmpVersion(A.SourceVerStr(), B.SourceVerStr()); + if (verret != 0) + return verret > 0; + return strcmp(A.ParentPkg().Name(), B.ParentPkg().Name()) < 0; + }); + auto const prvsize = providers.size(); + providers.erase(std::unique(providers.begin(), providers.end(), + [](pkgCache::VerIterator const &A, pkgCache::VerIterator const &B) { + return strcmp(A.SourcePkgName(), B.SourcePkgName()) == 0 && + strcmp(A.SourceVerStr(), B.SourceVerStr()) != 0; + }), providers.end()); + for (auto && PV: providers) + { + auto const PP = PV.ParentPkg(); + if (debug_autoremove) + std::clog << "Following dep: " << APT::PrettyDep(this, D) + << ", provided by " << PP.FullName() << " " << PV.VerStr() + << " (" << providers.size() << "/" << prvsize << ")"<< std::endl; + MarkPackage(PP, PV, follow_recommends, follow_suggests); + } } // now deal with the real part of the package diff --git a/test/integration/test-apt-get-autoremove b/test/integration/test-apt-get-autoremove index 7a28c51f1..17dba9aec 100755 --- a/test/integration/test-apt-get-autoremove +++ b/test/integration/test-apt-get-autoremove @@ -108,3 +108,39 @@ testdpkgnotinstalled 'po-debconf' 'debhelper' testmarkedauto testsuccess aptget install debhelper --solver apt -y -o Debug::pkgDepCache::Marker=1 testmarkedauto 'po-debconf' + +insertinstalledpackage 'bar' 'all' '1' 'Depends: foo-provider' +insertinstalledpackage 'foo-multi1-1' 'all' '1' 'Provides: foo-provider +Source: foo-multi (1)' +insertinstalledpackage 'foo-multi1-2' 'all' '1' 'Provides: foo-provider +Source: foo-multi (2)' +insertinstalledpackage 'foo-multi1-3' 'all' '1' 'Provides: foo-provider +Source: foo-multi (3)' +insertinstalledpackage 'foo-multi2-1' 'all' '1' 'Provides: foo-provider +Source: foo-multi (1)' +insertinstalledpackage 'foo-multi2-2' 'all' '1' 'Provides: foo-provider +Source: foo-multi (2)' +insertinstalledpackage 'foo-multi2-3' 'all' '1' 'Provides: foo-provider +Source: foo-multi (3)' +insertinstalledpackage 'foo-plus-1' 'all' '1' 'Provides: foo-provider +Source: foo-plus (1)' +insertinstalledpackage 'foo-plus-2' 'all' '1' 'Provides: foo-provider +Source: foo-plus (2)' +insertinstalledpackage 'foo-plus-3' 'all' '1' 'Provides: foo-provider +Source: foo-plus (3)' +insertinstalledpackage 'foo-single-1' 'all' '1' 'Provides: foo-provider' +insertinstalledpackage 'foo-single-2' 'all' '1' 'Provides: foo-provider' + +testsuccess aptmark auto 'foo-*' +testsuccessequal 'Reading package lists... +Building dependency tree... +Reading state information... +The following packages will be REMOVED: + foo-multi1-1 foo-multi1-2 foo-multi2-1 foo-multi2-2 foo-plus-1 foo-plus-2 +0 upgraded, 0 newly installed, 6 to remove and 0 not upgraded. +Remv foo-multi1-1 [1] +Remv foo-multi1-2 [1] +Remv foo-multi2-1 [1] +Remv foo-multi2-2 [1] +Remv foo-plus-1 [1] +Remv foo-plus-2 [1]' apt autoremove -s |