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, install each essential package which is not installed
- (and not provided by another package in the same name group) */
- std::string essential = _config->Find("pkgCacheGen::Essential", "all");
- if (essential == "all")
- {
- for (pkgCache::GrpIterator G = Cache.GrpBegin(); G.end() == false; ++G)
- {
- bool isEssential = false;
- bool instEssential = false;
- for (pkgCache::PkgIterator P = G.PackageList(); P.end() == false; P = G.NextPkg(P))
- {
- if ((P->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
- continue;
- isEssential = true;
- if (Cache[P].Install() == true)
- {
- instEssential = true;
- break;
- }
- }
- if (isEssential == false || instEssential == true)
- continue;
- pkgCache::PkgIterator P = G.FindPreferredPkg();
- Cache.MarkInstall(P, true, 0, false);
- }
- }
- else if (essential != "none")
- 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 /*{{{*/
// ---------------------------------------------------------------------
/* */
unsigned long Size = Cache.Head().PackageCount;
memset(Scores,0,sizeof(*Scores)*Size);
- // Maps to pkgCache::State::VerPriority
- // which is "Important Required Standard Optional Extra"
- // (yes, that is confusing, the order of pkgCache::State::VerPriority
- // needs to be adjusted but that requires a ABI break)
+ // maps to pkgCache::State::VerPriority:
+ // Required Important Standard Optional Extra
int PrioMap[] = {
0,
- _config->FindI("pkgProblemResolver::Scores::Important",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)
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];
}
}
}
while (Again == true);
- if (Debug == true)
- clog << "Starting" << endl;
+ if (Debug == true) {
+ clog << "Starting pkgProblemResolver with broken count: "
+ << Cache.BrokenCount() << endl;
+ }
MakeScores();
}
}
- 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
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);
qsort(List,Count,sizeof(*List),PrioComp);
}
/*}}}*/
-// ListUpdate - construct Fetcher and 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 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;
-
- return AcquireUpdate(Fetcher, PulseInterval, true);
-}
- /*}}}*/
-// AcquireUpdate - take Fetcher and update the cache files /*{{{*/
-// ---------------------------------------------------------------------
-/* This is a simple wrapper to update the cache with a provided acquire
- * If you only need control over Status and the used SourcesList use
- * ListUpdate method instead.
- */
-bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval,
- bool const RunUpdateScripts, bool const ListCleanup)
-{
- // Run scripts
- if (RunUpdateScripts == true)
- RunScripts("APT::Update::Pre-Invoke");
-
- pkgAcquire::RunResult res;
- 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 && ListCleanup == true &&
- (_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 (RunUpdateScripts == true)
- {
- if(!TransientNetworkFailure && !Failed)
- RunScripts("APT::Update::Post-Invoke-Success");
-
- // Run the other scripts
- RunScripts("APT::Update::Post-Invoke");
- }
- return true;
-}
- /*}}}*/