X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/dcaa1185506986142bccd990a5dca4c6ec1228cf..790d41f6372871e527f3fc9da66d049937b4c780:/apt-pkg/algorithms.cc diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index ed3534f0d..8644a8138 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -58,6 +58,12 @@ pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache), FileNames[I] = Jnk; } /*}}}*/ +// Simulate::~Simulate - Destructor /*{{{*/ +pkgSimulate::~pkgSimulate() +{ + delete[] Flags; +} + /*}}}*/ // Simulate::Describe - Describe a package /*{{{*/ // --------------------------------------------------------------------- /* Parameter Current == true displays the current package version, @@ -188,6 +194,11 @@ bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge) { // Adapt the iterator PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); + if (Pkg.end() == true) + { + std::cerr << (Purge ? "Purg" : "Remv") << " invalid package " << iPkg.FullName() << std::endl; + return false; + } Flags[Pkg->ID] = 3; Sim.MarkDelete(Pkg); @@ -276,13 +287,13 @@ bool pkgApplyStatus(pkgDepCache &Cache) Cache[I].CandidateVerIter(Cache).Downloadable() == true) Cache.MarkInstall(I, true, 0, false); else - Cache.MarkDelete(I); + Cache.MarkDelete(I, false, 0, false); } break; // This means removal failed case pkgCache::State::HalfInstalled: - Cache.MarkDelete(I); + Cache.MarkDelete(I, false, 0, false); break; default: @@ -325,149 +336,6 @@ bool pkgFixBroken(pkgDepCache &Cache) return Fix.Resolve(true); } /*}}}*/ -// DistUpgrade - Distribution upgrade /*{{{*/ -// --------------------------------------------------------------------- -/* This autoinstalls every package and then force installs every - pre-existing package. This creates the initial set of conditions which - most likely contain problems because too many things were installed. - - The problem resolver is used to resolve the problems. - */ -bool pkgDistUpgrade(pkgDepCache &Cache) -{ - std::string const solver = _config->Find("APT::Solver", "internal"); - if (solver != "internal") { - OpTextProgress Prog(*_config); - return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog); - } - - 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) - if (I->CurrentVer != 0) - Cache.MarkInstall(I, true, 0, false); - - /* Now, auto upgrade all essential packages - this ensures that - the essential packages are present and working */ - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) - Cache.MarkInstall(I, true, 0, false); - - /* We do it again over all previously installed packages to force - conflict resolution on them all. */ - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if (I->CurrentVer != 0) - Cache.MarkInstall(I, false, 0, false); - - pkgProblemResolver Fix(&Cache); - - // Hold back held packages. - if (_config->FindB("APT::Ignore-Hold",false) == false) - { - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - { - if (I->SelectedState == pkgCache::State::Hold) - { - Fix.Protect(I); - Cache.MarkKeep(I, false, false); - } - } - } - - return Fix.Resolve(); -} - /*}}}*/ -// AllUpgrade - Upgrade as many packages as possible /*{{{*/ -// --------------------------------------------------------------------- -/* Right now the system must be consistent before this can be called. - It also will not change packages marked for install, it only tries - to install packages not marked for install */ -bool pkgAllUpgrade(pkgDepCache &Cache) -{ - std::string const solver = _config->Find("APT::Solver", "internal"); - if (solver != "internal") { - OpTextProgress Prog(*_config); - return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog); - } - - pkgDepCache::ActionGroup group(Cache); - - pkgProblemResolver Fix(&Cache); - - if (Cache.BrokenCount() != 0) - return false; - - // Upgrade all installed packages - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - { - if (Cache[I].Install() == true) - Fix.Protect(I); - - if (_config->FindB("APT::Ignore-Hold",false) == false) - if (I->SelectedState == pkgCache::State::Hold) - continue; - - if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) - Cache.MarkInstall(I, false, 0, false); - } - - return Fix.ResolveByKeep(); -} - /*}}}*/ -// MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/ -// --------------------------------------------------------------------- -/* This simply goes over the entire set of packages and tries to keep - each package marked for upgrade. If a conflict is generated then - the package is restored. */ -bool pkgMinimizeUpgrade(pkgDepCache &Cache) -{ - pkgDepCache::ActionGroup group(Cache); - - if (Cache.BrokenCount() != 0) - return false; - - // We loop for 10 tries to get the minimal set size. - bool Change = false; - unsigned int Count = 0; - do - { - Change = false; - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - { - // Not interesting - if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) - continue; - - // Keep it and see if that is OK - Cache.MarkKeep(I, false, false); - if (Cache.BrokenCount() != 0) - Cache.MarkInstall(I, false, 0, false); - else - { - // If keep didnt actually do anything then there was no change.. - if (Cache[I].Upgrade() == false) - Change = true; - } - } - ++Count; - } - while (Change == true && Count < 10); - - if (Cache.BrokenCount() != 0) - return _error->Error("Internal Error in pkgMinimizeUpgrade"); - - return true; -} - /*}}}*/ // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -514,11 +382,12 @@ void pkgProblemResolver::MakeScores() unsigned long Size = Cache.Head().PackageCount; memset(Scores,0,sizeof(*Scores)*Size); - // Important Required Standard Optional Extra + // maps to pkgCache::State::VerPriority: + // Required Important Standard Optional Extra int PrioMap[] = { 0, - _config->FindI("pkgProblemResolver::Scores::Important",3), - _config->FindI("pkgProblemResolver::Scores::Required",2), + _config->FindI("pkgProblemResolver::Scores::Required",3), + _config->FindI("pkgProblemResolver::Scores::Important",2), _config->FindI("pkgProblemResolver::Scores::Standard",1), _config->FindI("pkgProblemResolver::Scores::Optional",-1), _config->FindI("pkgProblemResolver::Scores::Extra",-2) @@ -532,11 +401,11 @@ void pkgProblemResolver::MakeScores() if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true) clog << "Settings used to calculate pkgProblemResolver::Scores::" << endl - << " Important => " << PrioMap[1] << endl - << " Required => " << PrioMap[2] << endl - << " Standard => " << PrioMap[3] << endl - << " Optional => " << PrioMap[4] << endl - << " Extra => " << PrioMap[5] << endl + << " Required => " << PrioMap[pkgCache::State::Required] << endl + << " Important => " << PrioMap[pkgCache::State::Important] << endl + << " Standard => " << PrioMap[pkgCache::State::Standard] << endl + << " Optional => " << PrioMap[pkgCache::State::Optional] << endl + << " Extra => " << PrioMap[pkgCache::State::Extra] << endl << " Essentials => " << PrioEssentials << endl << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete << endl << " Depends => " << PrioDepends << endl @@ -556,7 +425,8 @@ void pkgProblemResolver::MakeScores() essantial package above most other packages but low enough to allow an obsolete essential packages to be removed by a conflicts on a powerfull normal package (ie libc6) */ - if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential + || (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) Score += PrioEssentials; // We transform the priority @@ -608,7 +478,10 @@ void pkgProblemResolver::MakeScores() D->Type != pkgCache::Dep::Recommends)) continue; - Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]); + // Do not propagate negative scores otherwise + // an extra (-2) package might score better than an optional (-1) + if (OldScores[D.ParentPkg()->ID] > 0) + Scores[I->ID] += OldScores[D.ParentPkg()->ID]; } } @@ -631,7 +504,8 @@ void pkgProblemResolver::MakeScores() { if ((Flags[I->ID] & Protected) != 0) Scores[I->ID] += AddProtected; - if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential || + (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) Scores[I->ID] += AddEssential; } } @@ -736,7 +610,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) if (WasKept == true) Cache.MarkKeep(Pkg, false, false); else - Cache.MarkDelete(Pkg); + Cache.MarkDelete(Pkg, false, 0, false); return false; } @@ -801,8 +675,10 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) } while (Again == true); - if (Debug == true) - clog << "Starting" << endl; + if (Debug == true) { + clog << "Starting pkgProblemResolver with broken count: " + << Cache.BrokenCount() << endl; + } MakeScores(); @@ -830,8 +706,10 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) } } - if (Debug == true) - clog << "Starting 2" << endl; + if (Debug == true) { + clog << "Starting 2 pkgProblemResolver with broken count: " + << Cache.BrokenCount() << endl; + } /* Now consider all broken packages. For each broken package we either remove the package or fix it's problem. We do this once, it should @@ -865,7 +743,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) OldBreaks < Cache.BrokenCount()) { if (OldVer == 0) - Cache.MarkDelete(I); + Cache.MarkDelete(I, false, 0, false); else Cache.MarkKeep(I, false, false); } @@ -904,7 +782,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) { if (Debug == true) clog << " Or group remove for " << I.FullName(false) << endl; - Cache.MarkDelete(I); + Cache.MarkDelete(I, false, 0, false); Change = true; } } @@ -1039,7 +917,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) { if (Debug == true) clog << " Removing " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl; - Cache.MarkDelete(I); + Cache.MarkDelete(I, false, 0, false); if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID]) Scores[I->ID] = Scores[Pkg->ID]; } @@ -1128,7 +1006,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) if (Debug == true) clog << " Removing " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl; if (InOr == false) - Cache.MarkDelete(I); + Cache.MarkDelete(I, false, 0, false); } Change = true; @@ -1155,7 +1033,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) { if (Debug == true) clog << " Fixing " << I.FullName(false) << " via remove of " << J->Pkg.FullName(false) << endl; - Cache.MarkDelete(J->Pkg); + Cache.MarkDelete(J->Pkg, false, 0, false); } } else @@ -1381,18 +1259,26 @@ bool pkgProblemResolver::ResolveByKeepInternal() continue; // Restart again. - if (K == LastStop) - return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false).c_str()); + if (K == LastStop) { + // I is an iterator based off our temporary package list, + // so copy the name we need before deleting the temporary list + std::string const LoopingPackage = I.FullName(false); + delete[] PList; + return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.", LoopingPackage.c_str()); + } LastStop = K; K = PList - 1; - } + } + delete[] PList; return true; } /*}}}*/ -// ProblemResolver::InstallProtect - Install all protected packages /*{{{*/ +// ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/ // --------------------------------------------------------------------- -/* This is used to make sure protected packages are installed */ +/* Actions issued with FromUser bit set are protected from further + modification (expect by other calls with FromUser set) nowadays , so we + don't need to reissue actions here, they are already set in stone. */ void pkgProblemResolver::InstallProtect() { pkgDepCache::ActionGroup group(Cache); @@ -1430,6 +1316,13 @@ static int PrioComp(const void *A,const void *B) if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential && (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) return -1; + + if ((L.ParentPkg()->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important && + (R.ParentPkg()->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important) + return 1; + if ((L.ParentPkg()->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important && + (R.ParentPkg()->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) + return -1; if (L->Priority != R->Priority) return R->Priority - L->Priority; @@ -1444,87 +1337,3 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List) qsort(List,Count,sizeof(*List),PrioComp); } /*}}}*/ -// ListUpdate - update the cache files /*{{{*/ -// --------------------------------------------------------------------- -/* This is a simple wrapper to update the cache. it will fetch stuff - * from the network (or any other sources defined in sources.list) - */ -bool ListUpdate(pkgAcquireStatus &Stat, - pkgSourceList &List, - int PulseInterval) -{ - pkgAcquire::RunResult res; - pkgAcquire Fetcher; - if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false) - return false; - - // Populate it with the source selection - if (List.GetIndexes(&Fetcher) == false) - return false; - - // Run scripts - RunScripts("APT::Update::Pre-Invoke"); - - // check arguments - if(PulseInterval>0) - res = Fetcher.Run(PulseInterval); - else - res = Fetcher.Run(); - - if (res == pkgAcquire::Failed) - return false; - - bool Failed = false; - bool TransientNetworkFailure = false; - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); - I != Fetcher.ItemsEnd(); ++I) - { - if ((*I)->Status == pkgAcquire::Item::StatDone) - continue; - - (*I)->Finished(); - - ::URI uri((*I)->DescURI()); - uri.User.clear(); - uri.Password.clear(); - string descUri = string(uri); - _error->Warning(_("Failed to fetch %s %s\n"), descUri.c_str(), - (*I)->ErrorText.c_str()); - - if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError) - { - TransientNetworkFailure = true; - continue; - } - - Failed = true; - } - - // Clean out any old list files - // Keep "APT::Get::List-Cleanup" name for compatibility, but - // this is really a global option for the APT library now - if (!TransientNetworkFailure && !Failed && - (_config->FindB("APT::Get::List-Cleanup",true) == true && - _config->FindB("APT::List-Cleanup",true) == true)) - { - if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false || - Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false) - // something went wrong with the clean - return false; - } - - if (TransientNetworkFailure == true) - _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.")); - - - // Run the success scripts if all was fine - if(!TransientNetworkFailure && !Failed) - RunScripts("APT::Update::Post-Invoke-Success"); - - // Run the other scripts - RunScripts("APT::Update::Post-Invoke"); - return true; -} - /*}}}*/