X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/47f6d1b72bc883ecdc00542da4c824a5c4fb79fa..85bcab87a3c6f8d4b1369a5a4bd5a73a28f41dce:/apt-pkg/algorithms.cc diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 12c5b8710..b55ff2897 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -20,12 +20,15 @@ #include #include #include - +#include + #include #include #include #include #include + +#include /*}}}*/ using namespace std; @@ -90,21 +93,6 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) Describe(Pkg,cout,true,true); Sim.MarkInstall(Pkg,false); - if (strcmp(Pkg.Arch(),"all") == 0) - { - pkgCache::GrpIterator G = Pkg.Group(); - pkgCache::GrpIterator iG = iPkg.Group(); - for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) - { - if (strcmp(P.Arch(), "all") == 0) - continue; - if (iG.FindPkg(P.Arch())->CurrentVer == 0) - continue; - Flags[P->ID] = 1; - Sim.MarkInstall(P, false); - } - } - // Look for broken conflicts+predepends. for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++) { @@ -150,19 +138,6 @@ bool pkgSimulate::Configure(PkgIterator iPkg) Flags[Pkg->ID] = 2; - if (strcmp(Pkg.Arch(),"all") == 0) - { - pkgCache::GrpIterator G = Pkg.Group(); - for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) - { - if (strcmp(P.Arch(), "all") == 0) - continue; - if (Flags[P->ID] == 1) - Flags[P->ID] = 2; - } - } - -// Sim.MarkInstall(Pkg,false); if (Sim[Pkg].InstBroken() == true) { cout << "Conf " << Pkg.FullName(false) << " broken" << endl; @@ -187,7 +162,7 @@ bool pkgSimulate::Configure(PkgIterator iPkg) } cout << endl; - _error->Error("Conf Broken %s",Pkg.FullName(false)); + _error->Error("Conf Broken %s",Pkg.FullName(false).c_str()); } else { @@ -214,21 +189,6 @@ bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge) Flags[Pkg->ID] = 3; Sim.MarkDelete(Pkg); - if (strcmp(Pkg.Arch(),"all") == 0) - { - pkgCache::GrpIterator G = Pkg.Group(); - pkgCache::GrpIterator iG = iPkg.Group(); - for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) - { - if (strcmp(P.Arch(), "all") == 0) - continue; - if (iG.FindPkg(P.Arch())->CurrentVer == 0) - continue; - Flags[P->ID] = 3; - Sim.MarkDelete(P); - } - } - if (Purge == true) cout << "Purg "; else @@ -290,7 +250,7 @@ bool pkgApplyStatus(pkgDepCache &Cache) Cache.MarkInstall(I, false, 0, false); else return _error->Error(_("The package %s needs to be reinstalled, " - "but I can't find an archive for it."),I.FullName(true)); + "but I can't find an archive for it."),I.FullName(true).c_str()); } continue; @@ -325,7 +285,7 @@ bool pkgApplyStatus(pkgDepCache &Cache) default: if (I->InstState != pkgCache::State::Ok) return _error->Error("The package %s is not ok and I " - "don't know how to fix it!",I.FullName(false)); + "don't know how to fix it!",I.FullName(false).c_str()); } } return true; @@ -374,6 +334,13 @@ bool pkgDistUpgrade(pkgDepCache &Cache) { pkgDepCache::ActionGroup group(Cache); + /* Upgrade all installed packages first without autoinst to help the resolver + in versioned or-groups to upgrade the old solver instead of installing + a new one (if the old solver is not the first one [anymore]) */ + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (I->CurrentVer != 0) + Cache.MarkInstall(I, false, 0, false); + /* Auto upgrade all installed packages, this provides the basis for the installation */ for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) @@ -767,7 +734,31 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) return true; } /*}}}*/ -// ProblemResolver::Resolve - Run the resolution pass /*{{{*/ +// ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool pkgProblemResolver::Resolve(bool BrokenFix) +{ + std::string const solver = _config->Find("APT::Solver::Name", "internal"); + if (solver != "internal") + { + FILE* output = fopen("/tmp/scenario.log", "w"); + edspWriter::WriteScenario(Cache, output); + fclose(output); + output = fopen("/tmp/request.log", "w"); + edspWriter::WriteRequest(Cache, output); + fclose(output); + if (ResolveInternal(BrokenFix) == false) + return false; + output = fopen("/tmp/solution.log", "w"); + edspWriter::WriteSolution(Cache, output); + fclose(output); + return true; + } + return ResolveInternal(BrokenFix); +} + /*}}}*/ +// ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/ // --------------------------------------------------------------------- /* This routines works by calculating a score for each package. The score is derived by considering the package's priority and all reverse @@ -781,12 +772,10 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) The BrokenFix flag enables a mode where the algorithm tries to upgrade packages to advoid problems. */ -bool pkgProblemResolver::Resolve(bool BrokenFix) +bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) { pkgDepCache::ActionGroup group(Cache); - unsigned long Size = Cache.Head().PackageCount; - // Record which packages are marked for install bool Again = false; do @@ -816,7 +805,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) clog << "Starting" << endl; MakeScores(); - + + unsigned long const Size = Cache.Head().PackageCount; + /* We have to order the packages so that the broken fixing pass operates from highest score to lowest. This prevents problems when high score packages cause the removal of lower score packages that @@ -847,6 +838,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) not be possible for a loop to form (that is a < b < c and fixing b by changing a breaks c) */ bool Change = true; + bool const TryFixByInstall = _config->FindB("pkgProblemResolver::FixByInstall", true); for (int Counter = 0; Counter != 10 && Change == true; Counter++) { Change = false; @@ -863,7 +855,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) (Flags[I->ID] & ReInstateTried) == 0) { if (Debug == true) - clog << " Try to Re-Instate " << I.FullName(false) << endl; + clog << " Try to Re-Instate (" << Counter << ") " << I.FullName(false) << endl; unsigned long OldBreaks = Cache.BrokenCount(); pkgCache::Version *OldVer = Cache[I].InstallVer; Flags[I->ID] &= ReInstateTried; @@ -886,7 +878,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) continue; if (Debug == true) - clog << "Investigating " << I << endl; + clog << "Investigating (" << Counter << ") " << I << endl; // Isolate the problem dependency PackageKill KillList[100]; @@ -904,9 +896,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if (Start == End) { // Decide what to do - if (InOr == true) + if (InOr == true && OldEnd == LEnd) { - if (OldEnd == LEnd && OrOp == OrRemove) + if (OrOp == OrRemove) { if ((Flags[I->ID] & Protected) != Protected) { @@ -914,9 +906,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) clog << " Or group remove for " << I.FullName(false) << endl; Cache.MarkDelete(I); Change = true; - } - } - if (OldEnd == LEnd && OrOp == OrKeep) + } + } + else if (OrOp == OrKeep) { if (Debug == true) clog << " Or group keep for " << I.FullName(false) << endl; @@ -986,6 +978,23 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) pkgCache::VerIterator Ver(Cache,*V); pkgCache::PkgIterator Pkg = Ver.ParentPkg(); + /* This is a conflicts, and the version we are looking + at is not the currently selected version of the + package, which means it is not necessary to + remove/keep */ + if (Cache[Pkg].InstallVer != Ver && + (Start->Type == pkgCache::Dep::Conflicts || + Start->Type == pkgCache::Dep::DpkgBreaks || + Start->Type == pkgCache::Dep::Obsoletes)) + { + if (Debug) + clog << " Conflicts//Breaks against version " + << Ver.VerStr() << " for " << Pkg.Name() + << " but that is not InstVer, ignoring" + << endl; + continue; + } + if (Debug == true) clog << " Considering " << Pkg.FullName(false) << ' ' << (int)Scores[Pkg->ID] << " as a solution to " << I.FullName(false) << ' ' << (int)Scores[I->ID] << endl; @@ -1041,6 +1050,25 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID]) Scores[I->ID] = Scores[Pkg->ID]; } + else if (TryFixByInstall == true && + Start.TargetPkg()->CurrentVer == 0 && + Cache[Start.TargetPkg()].Delete() == false && + (Flags[Start.TargetPkg()->ID] & ToRemove) != ToRemove && + Cache.GetCandidateVer(Start.TargetPkg()).end() == false) + { + /* Before removing or keeping the package with the broken dependency + try instead to install the first not previously installed package + solving this dependency. This helps every time a previous solver + is removed by the resolver because of a conflict or alike but it is + dangerous as it could trigger new breaks/conflicts… */ + if (Debug == true) + clog << " Try Installing " << Start.TargetPkg() << " before changing " << I.FullName(false) << std::endl; + unsigned long const OldBroken = Cache.BrokenCount(); + Cache.MarkInstall(Start.TargetPkg(), true, 1, false); + // FIXME: we should undo the complete MarkInstall process here + if (Cache[Start.TargetPkg()].InstBroken() == true || Cache.BrokenCount() > OldBroken) + Cache.MarkDelete(Start.TargetPkg(), false, 1, false); + } } } @@ -1050,22 +1078,14 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) } else { - /* This is a conflicts, and the version we are looking - at is not the currently selected version of the - package, which means it is not necessary to - remove/keep */ - if (Cache[Pkg].InstallVer != Ver && - (Start->Type == pkgCache::Dep::Conflicts || - Start->Type == pkgCache::Dep::Obsoletes)) - continue; - if (Start->Type == pkgCache::Dep::DpkgBreaks) { // first, try upgradring the package, if that // does not help, the breaks goes onto the // kill list + // // FIXME: use DoUpgrade(Pkg) instead? - if (Cache[End] & pkgDepCache::DepGCVer) + if (Cache[End] & pkgDepCache::DepGCVer) { if (Debug) clog << " Upgrading " << Pkg.FullName(false) << " due to Breaks field in " << I.FullName(false) << endl; @@ -1325,7 +1345,7 @@ bool pkgProblemResolver::ResolveByKeep() // Restart again. if (K == LastStop) - return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false)); + return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false).c_str()); LastStop = K; K = PList - 1; } @@ -1457,9 +1477,9 @@ bool ListUpdate(pkgAcquireStatus &Stat, } if (TransientNetworkFailure == true) - _error->Warning(_("Some index files failed to download, they have been ignored, or old ones used instead.")); + _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead.")); else if (Failed == true) - return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead.")); + return _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead.")); // Run the success scripts if all was fine