diff options
author | Michael Vogt <mvo@debian.org> | 2013-10-22 21:24:13 +0200 |
---|---|---|
committer | Michael Vogt <mvo@debian.org> | 2013-10-22 21:24:13 +0200 |
commit | 4c9234d668bc1a250fd1af4c5d90497a08be67fd (patch) | |
tree | 6f7851c01a98a98013625af3de28cceeab3e2db9 /apt-pkg | |
parent | c08cf1dc784a98a253296a51433f6de7d16d3125 (diff) | |
parent | 3f506f684c6199a9a2bc68365732a9c00dc551c1 (diff) |
Merge remote-tracking branch 'mvo/feature/upgrade-api' into debian/sid
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/algorithms.cc | 310 | ||||
-rw-r--r-- | apt-pkg/algorithms.h | 18 | ||||
-rw-r--r-- | apt-pkg/makefile | 5 | ||||
-rw-r--r-- | apt-pkg/update.cc | 126 | ||||
-rw-r--r-- | apt-pkg/update.h | 21 | ||||
-rw-r--r-- | apt-pkg/upgrade.cc | 263 | ||||
-rw-r--r-- | apt-pkg/upgrade.h | 30 |
7 files changed, 450 insertions, 323 deletions
diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 69d4acd83..8644a8138 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -336,217 +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, 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(); -} - /*}}}*/ -// AllUpgradeNoDelete - Upgrade without removing packages /*{{{*/ -// --------------------------------------------------------------------- -/* Right now the system must be consistent before this can be called. - * Upgrade as much as possible without deleting anything (useful for - * stable systems) - */ -bool pkgAllUpgradeNoDelete(pkgDepCache &Cache) -{ - pkgDepCache::ActionGroup group(Cache); - - pkgProblemResolver Fix(&Cache); - - if (Cache.BrokenCount() != 0) - return false; - - // provide the initial set of stuff we want to upgrade by marking - // all upgradable packages for upgrade - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - { - if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) - { - if (_config->FindB("APT::Ignore-Hold",false) == false) - if (I->SelectedState == pkgCache::State::Hold) - continue; - - Cache.MarkInstall(I, false, 0, false); - } - } - - // then let auto-install loose - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if (Cache[I].Install()) - Cache.MarkInstall(I, true, 0, false); - - // ... but it may remove stuff, we we need to clean up afterwards again - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if (Cache[I].Delete() == true) - Cache.MarkKeep(I, false, false); - - // resolve remaining issues via keep - 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 /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -1548,102 +1337,3 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List) 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; -} - /*}}}*/ diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index a499db8ba..80f6578eb 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -40,10 +40,15 @@ #ifndef APT_8_CLEANER_HEADERS #include <apt-pkg/acquire.h> +// include pkg{DistUpgrade,AllUpgrade,MiniizeUpgrade} here for compatiblity using std::ostream; #endif -class pkgAcquireStatus; +#ifndef APT_9_CLEANER_HEADERS +#include <apt-pkg/upgrade.h> +#include <apt-pkg/update.h> +#endif + class pkgSimulate : public pkgPackageManager /*{{{*/ { @@ -85,6 +90,7 @@ private: /*}}}*/ class pkgProblemResolver /*{{{*/ { + private: /** \brief dpointer placeholder (for later in case we need it) */ void *d; @@ -140,20 +146,10 @@ class pkgProblemResolver /*{{{*/ ~pkgProblemResolver(); }; /*}}}*/ -bool pkgDistUpgrade(pkgDepCache &Cache); bool pkgApplyStatus(pkgDepCache &Cache); bool pkgFixBroken(pkgDepCache &Cache); -bool pkgAllUpgrade(pkgDepCache &Cache); - -bool pkgAllUpgradeNoDelete(pkgDepCache &Cache); - -bool pkgMinimizeUpgrade(pkgDepCache &Cache); - void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List); -bool ListUpdate(pkgAcquireStatus &progress, pkgSourceList &List, int PulseInterval=0); -bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval = 0, - bool const RunUpdateScripts = true, bool const ListCleanup = true); #endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 59729faf5..dc943aad4 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -43,7 +43,8 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \ srcrecords.cc cachefile.cc versionmatch.cc policy.cc \ pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \ - aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc + aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc \ + upgrade.cc update.cc HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ orderlist.h sourcelist.h packagemanager.h tagfile.h \ init.h pkgcache.h version.h progress.h pkgrecords.h \ @@ -51,7 +52,7 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ clean.h srcrecords.h cachefile.h versionmatch.h policy.h \ pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \ - cachefilter.h cacheset.h edsp.h + cachefilter.h cacheset.h edsp.h upgrade.h update.h # Source code for the debian specific components # In theory the deb headers do not need to be exported.. diff --git a/apt-pkg/update.cc b/apt-pkg/update.cc new file mode 100644 index 000000000..97be5490b --- /dev/null +++ b/apt-pkg/update.cc @@ -0,0 +1,126 @@ + +// Include Files /*{{{*/ +#include <config.h> + +#include <apt-pkg/algorithms.h> +#include <apt-pkg/update.h> +#include <apt-pkg/error.h> +#include <apt-pkg/configuration.h> +#include <apt-pkg/version.h> +#include <apt-pkg/sptr.h> +#include <apt-pkg/acquire-item.h> +#include <apt-pkg/edsp.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/progress.h> + +#include <sys/types.h> +#include <cstdlib> +#include <algorithm> +#include <iostream> +#include <stdio.h> + +#include <apti18n.h> + /*}}}*/ + +using namespace std; + +// 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; +} + /*}}}*/ diff --git a/apt-pkg/update.h b/apt-pkg/update.h new file mode 100644 index 000000000..3835644de --- /dev/null +++ b/apt-pkg/update.h @@ -0,0 +1,21 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Update - ListUpdate releated code + + ##################################################################### */ + /*}}}*/ + +#ifndef PKGLIB_UPDATE_H +#define PKGLIB_UPDATE_H + +class pkgAcquireStatus; + + +bool ListUpdate(pkgAcquireStatus &progress, pkgSourceList &List, int PulseInterval=0); +bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval = 0, + bool const RunUpdateScripts = true, bool const ListCleanup = true); + + +#endif diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc new file mode 100644 index 000000000..f06f6d40d --- /dev/null +++ b/apt-pkg/upgrade.cc @@ -0,0 +1,263 @@ + +// Include Files /*{{{*/ +#include <config.h> + +#include <apt-pkg/algorithms.h> +#include <apt-pkg/upgrade.h> +#include <apt-pkg/error.h> +#include <apt-pkg/configuration.h> +#include <apt-pkg/version.h> +#include <apt-pkg/sptr.h> +#include <apt-pkg/acquire-item.h> +#include <apt-pkg/edsp.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/progress.h> + +#include <sys/types.h> +#include <cstdlib> +#include <algorithm> +#include <iostream> +#include <stdio.h> + +#include <apti18n.h> + /*}}}*/ + +// 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(); +} + /*}}}*/ +// AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs /*{{{*/ +static bool pkgAllUpgradeNoNewPackages(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(); +} + /*}}}*/ +// AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/ +// --------------------------------------------------------------------- +/* Right now the system must be consistent before this can be called. + * Upgrade as much as possible without deleting anything (useful for + * stable systems) + */ +static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache) +{ + pkgDepCache::ActionGroup group(Cache); + + pkgProblemResolver Fix(&Cache); + + if (Cache.BrokenCount() != 0) + return false; + + // provide the initial set of stuff we want to upgrade by marking + // all upgradable packages for upgrade + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + { + if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) + { + if (_config->FindB("APT::Ignore-Hold",false) == false) + if (I->SelectedState == pkgCache::State::Hold) + continue; + + Cache.MarkInstall(I, false, 0, false); + } + } + + // then let auto-install loose + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (Cache[I].Install()) + Cache.MarkInstall(I, true, 0, false); + + // ... but it may remove stuff, we we need to clean up afterwards again + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (Cache[I].Delete() == true) + Cache.MarkKeep(I, false, false); + + // resolve remaining issues via keep + return Fix.ResolveByKeep(); +} + /*}}}*/ +// 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) +{ + return pkgAllUpgradeNoNewPackages(Cache); +} + /*}}}*/ +// 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; +} + /*}}}*/ +// APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/ +bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode) +{ + if (mode == 0) + { + return pkgDistUpgrade(Cache); + } + else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0) + { + return pkgAllUpgradeWithNewPackages(Cache); + } + else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_INSTALL_NEW_PACKAGES)) == 0) + { + return pkgAllUpgradeNoNewPackages(Cache); + } + else + _error->Error("pkgAllUpgrade called with unsupported mode %i", mode); + + return false; +} + /*}}}*/ diff --git a/apt-pkg/upgrade.h b/apt-pkg/upgrade.h new file mode 100644 index 000000000..c4973472f --- /dev/null +++ b/apt-pkg/upgrade.h @@ -0,0 +1,30 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Upgrade - Upgrade/DistUpgrade releated code + + ##################################################################### */ + /*}}}*/ + +#ifndef PKGLIB_UPGRADE_H +#define PKGLIB_UPGRADE_H + +namespace APT { + namespace Upgrade { + // FIXME: make this "enum class UpgradeMode {" once we enable c++11 + enum UpgradeMode { + FORBID_REMOVE_PACKAGES = 1, + FORBID_INSTALL_NEW_PACKAGES = 2, + }; + bool Upgrade(pkgDepCache &Cache, int UpgradeMode); + } +} + +// please use APT::Upgrade::Upgrade() instead +bool pkgDistUpgrade(pkgDepCache &Cache); +bool pkgAllUpgrade(pkgDepCache &Cache); +bool pkgMinimizeUpgrade(pkgDepCache &Cache); + + +#endif |