diff options
author | David Kalnischkies <david@kalnischkies.de> | 2015-08-21 19:59:33 +0200 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2015-08-27 11:24:07 +0200 |
commit | 9106d7c9692e91622a828f382b85fe592bfec81d (patch) | |
tree | 3e7fc8ff825046d9a2abb18d613b489c2493e1e4 | |
parent | 313f7d4ad08831de0a95a88ee4d62795aaad8a0c (diff) |
just-in-time removal of broken essential packages
We deal with Conflicts in SmartUnpack in pretty much the same way, but
Breaks weren't handled in SmartConfigure so that the remove was sheduled
after the configuration of the package breaking the to-be-removed.
Closes: 796070
-rw-r--r-- | apt-pkg/packagemanager.cc | 41 | ||||
-rw-r--r-- | apt-pkg/packagemanager.h | 1 | ||||
-rwxr-xr-x | test/integration/test-bug-796070-downgrade-realpkg | 23 | ||||
-rwxr-xr-x | test/integration/test-bug-796070-downgrade-simulate (renamed from test/integration/skip-bug-796070-downgrade) | 4 |
4 files changed, 64 insertions, 5 deletions
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 06ec986ed..ceeb60a03 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -268,6 +268,33 @@ bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D, return true; } /*}}}*/ +// PM::CheckRBreaks - Look for reverse breaks /*{{{*/ +bool pkgPackageManager::CheckRBreaks(PkgIterator const &Pkg, DepIterator D, + const char * const Ver) +{ + for (;D.end() == false; ++D) + { + if (D->Type != pkgCache::Dep::DpkgBreaks) + continue; + + PkgIterator const DP = D.ParentPkg(); + if (Cache[DP].Delete() == false) + continue; + + // Ignore self conflicts, ignore conflicts from irrelevant versions + if (D.IsIgnorable(Pkg) || D.ParentVer() != DP.CurrentVer()) + continue; + + if (Cache.VS().CheckDep(Ver, D->CompareOp, D.TargetVer()) == false) + continue; + + // no earlyremove() here as user has already agreed to the permanent removal + if (SmartRemove(DP) == false) + return _error->Error("Internal Error, Could not early remove %s (%d)",DP.FullName().c_str(), 4); + } + return true; +} + /*}}}*/ // PM::ConfigureAll - Run the all out configuration /*{{{*/ // --------------------------------------------------------------------- /* This configures every package. It is assumed they are all unpacked and @@ -561,6 +588,14 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) if (Bad == true) return _error->Error(_("Could not configure '%s'. "),Pkg.FullName().c_str()); + // Check for reverse conflicts. + if (CheckRBreaks(Pkg,Pkg.RevDependsList(), instVer.VerStr()) == false) + return false; + + for (PrvIterator P = instVer.ProvidesList(); P.end() == false; ++P) + if (Pkg->Group != P.OwnerPkg()->Group) + CheckRBreaks(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion()); + if (PkgLoop) return true; static std::string const conf = _config->Find("PackageManager::Configure","all"); @@ -847,7 +882,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c clog << OutputInDepth(Depth) << "Because of conflict knot, removing " << ConflictPkg.FullName() << " temporarily" << endl; } if (EarlyRemove(ConflictPkg, &End) == false) - return _error->Error("Internal Error, Could not early remove %s (2)",ConflictPkg.FullName().c_str()); + return _error->Error("Internal Error, Could not early remove %s (%d)",ConflictPkg.FullName().c_str(), 3); SomethingBad = true; continue; } @@ -889,7 +924,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c if (Debug) clog << OutputInDepth(Depth) << "So temprorary remove/deconfigure " << ConflictPkg.FullName() << " to satisfy " << End << endl; if (EarlyRemove(ConflictPkg, &End) == false) - return _error->Error("Internal Error, Could not early remove %s (2)",ConflictPkg.FullName().c_str()); + return _error->Error("Internal Error, Could not early remove %s (%d)",ConflictPkg.FullName().c_str(), 2); } } else @@ -901,7 +936,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c clog << OutputInDepth(Depth) << "Removing " << ConflictPkg.FullName() << " now to avoid " << End << endl; // no earlyremove() here as user has already agreed to the permanent removal if (SmartRemove(Pkg) == false) - return _error->Error("Internal Error, Could not early remove %s (1)",ConflictPkg.FullName().c_str()); + return _error->Error("Internal Error, Could not early remove %s (%d)",ConflictPkg.FullName().c_str(), 1); } } } diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 8de6ab3ad..e4d20fff4 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -76,6 +76,7 @@ class pkgPackageManager : protected pkgCache::Namespace void ImmediateAdd(PkgIterator P, bool UseInstallVer, unsigned const int &Depth = 0); virtual OrderResult OrderInstall(); bool CheckRConflicts(PkgIterator Pkg,DepIterator Dep,const char *Ver); + bool CheckRBreaks(PkgIterator const &Pkg,DepIterator Dep,const char * const Ver); bool CreateOrderList(); // Analysis helpers diff --git a/test/integration/test-bug-796070-downgrade-realpkg b/test/integration/test-bug-796070-downgrade-realpkg new file mode 100755 index 000000000..3ad4fda3e --- /dev/null +++ b/test/integration/test-bug-796070-downgrade-realpkg @@ -0,0 +1,23 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'i386' + +buildsimplenativepackage 'apt' 'all' '1.0.10.1' 'stable' 'Depends: libapt-pkg4.16 (>= 1.0.10.1)' +buildsimplenativepackage 'libapt-pkg4.16' 'all' '1.0.10.1' 'stable' 'Breaks: apt (<< 0.9.4~), libapt-inst1.5 (<< 0.9.9~)' +buildsimplenativepackage 'libapt-pkg5.0' 'all' '1.1~exp9' 'unstable' 'Breaks: apt (<< 1.1~exp4), libapt-inst1.5 (<< 0.9.9~)' +buildsimplenativepackage 'apt' 'all' '1.1~exp9' 'unstable' 'Depends: libapt-pkg5.0' + +setupaptarchive + +# Check with the APT name, aka essential +testsuccess aptget install apt -t stable -y +testsuccess aptget dist-upgrade -y + +testsuccess aptget install apt/stable -y --allow-downgrades -o Debug::pkgPackageManager=1 #-o Debug::pkgDpkgPM=1 +testdpkginstalled apt libapt-pkg4.16 +testdpkgnotinstalled libapt-pkg5.0 diff --git a/test/integration/skip-bug-796070-downgrade b/test/integration/test-bug-796070-downgrade-simulate index a435cfbf1..0b4817d39 100755 --- a/test/integration/skip-bug-796070-downgrade +++ b/test/integration/test-bug-796070-downgrade-simulate @@ -49,8 +49,8 @@ The following packages will be REMOVED: The following packages will be DOWNGRADED: eapt 0 upgraded, 0 newly installed, 1 downgraded, 1 to remove and 0 not upgraded. +Inst eapt [1.1~exp9] (1.0.10.1 unstable [all]) [elibapt-pkg5.0:i386 on eapt:i386] [elibapt-pkg5.0:i386 ] Remv elibapt-pkg5.0 [1.1~exp9] -Inst eapt [1.1~exp9] (1.0.10.1 unstable [all]) Conf eapt (1.0.10.1 unstable [all])' apt install -s eapt=1.0.10.1 @@ -62,6 +62,6 @@ The following packages will be REMOVED: The following packages will be DOWNGRADED: apt 0 upgraded, 0 newly installed, 1 downgraded, 1 to remove and 0 not upgraded. +Inst apt [1.1~exp9] (1.0.10.1 unstable [all]) [libapt-pkg5.0:i386 on apt:i386] [libapt-pkg5.0:i386 ] Remv libapt-pkg5.0 [1.1~exp9] -Inst apt [1.1~exp9] (1.0.10.1 unstable [all]) Conf apt (1.0.10.1 unstable [all])' apt install -s apt=1.0.10.1 |