X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/47f6d1b72bc883ecdc00542da4c824a5c4fb79fa..3c54407f8783d5e27363eabf41dbc3d031526ffe:/apt-pkg/algorithms.cc diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 12c5b8710..66c182b23 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -162,7 +162,28 @@ bool pkgSimulate::Configure(PkgIterator iPkg) } } -// Sim.MarkInstall(Pkg,false); + if (Sim[Pkg].InstBroken() == true) + { + /* We don't call Configure for Pseudo packages and if the 'all' is already installed + the simulation will think the pseudo package is not installed, so if something is + broken we walk over the dependencies and search for not installed pseudo packages */ + for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; D++) + { + if (Sim.IsImportantDep(D) == false || + (Sim[D] & pkgDepCache::DepInstall) != 0) + continue; + pkgCache::PkgIterator T = D.TargetPkg(); + if (T.end() == true || T->CurrentVer != 0 || Flags[T->ID] != 0) + continue; + pkgCache::PkgIterator A = T.Group().FindPkg("all"); + if (A.end() == true || A->VersionList == 0 || A->CurrentVer == 0 || + Cache.VS().CheckDep(A.CurVersion(), pkgCache::Dep::Equals, T.CandVersion()) == false) + continue; + Sim.MarkInstall(T, false); + Flags[T->ID] = 2; + } + } + if (Sim[Pkg].InstBroken() == true) { cout << "Conf " << Pkg.FullName(false) << " broken" << endl; @@ -187,7 +208,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 { @@ -290,7 +311,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 +346,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 +395,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++) @@ -847,6 +875,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 +892,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 +915,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 +933,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 +943,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 +1015,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 +1087,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 +1115,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 +1382,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 +1514,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