diff options
author | Michael Vogt <mvo@debian.org> | 2013-08-12 23:24:08 +0200 |
---|---|---|
committer | Michael Vogt <mvo@debian.org> | 2013-08-12 23:24:08 +0200 |
commit | b917917067e757c4479a344a263ef7cf43c00866 (patch) | |
tree | 2894b0e1260ed91f2bd205e2b2b3d25eed79b3d2 | |
parent | 713a2de01cc1a0b8dcd71a4137f8a099d22783b7 (diff) |
squash merge of the feature/apt-binary branch without the changes from experimental
45 files changed, 4281 insertions, 2107 deletions
@@ -13,6 +13,7 @@ default: startup all all headers library clean veryclean binary program doc manpages debiandoc test update-po startup dirs: $(MAKE) -C apt-pkg $@ $(MAKE) -C apt-inst $@ + $(MAKE) -C apt-private $@ $(MAKE) -C methods $@ $(MAKE) -C cmdline $@ $(MAKE) -C ftparchive $@ diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 85799a11b..69d4acd83 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -459,6 +459,49 @@ bool pkgAllUpgrade(pkgDepCache &Cache) 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 @@ -550,14 +593,12 @@ void pkgProblemResolver::MakeScores() 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) diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 7f58c8eed..a499db8ba 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -143,7 +143,11 @@ class 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); diff --git a/apt-pkg/cachefilter.cc b/apt-pkg/cachefilter.cc index 64cde41d1..57b9af159 100644 --- a/apt-pkg/cachefilter.cc +++ b/apt-pkg/cachefilter.cc @@ -55,6 +55,17 @@ PackageNameMatchesRegEx::~PackageNameMatchesRegEx() { /*{{{*/ } /*}}}*/ +// Fnmatch support /*{{{*/ +//---------------------------------------------------------------------- +bool PackageNameMatchesFnmatch::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/ + return fnmatch(Pattern.c_str(), Pkg.Name(), FNM_CASEFOLD) == 0; +} + /*}}}*/ +bool PackageNameMatchesFnmatch::operator() (pkgCache::GrpIterator const &Grp) {/*{{{*/ + return fnmatch(Pattern.c_str(), Grp.Name(), FNM_CASEFOLD) == 0; +} + /*}}}*/ + // CompleteArch to <kernel>-<cpu> tuple /*{{{*/ //---------------------------------------------------------------------- /* The complete architecture, consisting of <kernel>-<cpu>. */ diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h index 25cd43f47..f55d5c7f7 100644 --- a/apt-pkg/cachefilter.h +++ b/apt-pkg/cachefilter.h @@ -14,18 +14,41 @@ /*}}}*/ namespace APT { namespace CacheFilter { + +class PackageMatcher { + public: + virtual bool operator() (pkgCache::PkgIterator const &Pkg) { return false; }; + virtual bool operator() (pkgCache::GrpIterator const &Grp) { return false; }; + virtual bool operator() (pkgCache::VerIterator const &Ver) { return false; }; + + virtual ~PackageMatcher() {}; +}; + // PackageNameMatchesRegEx /*{{{*/ -class PackageNameMatchesRegEx { +class PackageNameMatchesRegEx : public PackageMatcher { /** \brief dpointer placeholder (for later in case we need it) */ void *d; regex_t* pattern; public: PackageNameMatchesRegEx(std::string const &Pattern); - bool operator() (pkgCache::PkgIterator const &Pkg); - bool operator() (pkgCache::GrpIterator const &Grp); + virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::GrpIterator const &Grp); ~PackageNameMatchesRegEx(); }; /*}}}*/ +// PackageNameMatchesFnmatch /*{{{*/ + class PackageNameMatchesFnmatch : public PackageMatcher{ + /** \brief dpointer placeholder (for later in case we need it) */ + void *d; + const std::string Pattern; +public: + PackageNameMatchesFnmatch(std::string const &Pattern) + : Pattern(Pattern) {}; + virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::GrpIterator const &Grp); + ~PackageNameMatchesFnmatch() {}; +}; + /*}}}*/ // PackageArchitectureMatchesSpecification /*{{{*/ /** \class PackageArchitectureMatchesSpecification \brief matching against architecture specification strings @@ -35,7 +58,7 @@ public: debian-policy ยง11.1 "Architecture specification strings". Examples: i386, mipsel, linux-any, any-amd64, any */ -class PackageArchitectureMatchesSpecification { +class PackageArchitectureMatchesSpecification : public PackageMatcher { std::string literal; std::string complete; bool isPattern; @@ -51,8 +74,8 @@ public: */ PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true); bool operator() (char const * const &arch); - bool operator() (pkgCache::PkgIterator const &Pkg); - bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::VerIterator const &Ver); ~PackageArchitectureMatchesSpecification(); }; /*}}}*/ diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 1fea4f94a..0147f7e86 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -155,6 +155,69 @@ bool PackageContainerInterface::FromRegEx(PackageContainerInterface * const pci, return true; } /*}}}*/ +// FromFnmatch - Returns the package defined by this fnmatch /*{{{*/ +bool +PackageContainerInterface::FromFnmatch(PackageContainerInterface * const pci, + pkgCacheFile &Cache, + std::string pattern, + CacheSetHelper &helper) +{ + static const char * const isfnmatch = ".?*[]!"; + if (pattern.find_first_of(isfnmatch) == std::string::npos) + return false; + + bool const wasEmpty = pci->empty(); + if (wasEmpty == true) + pci->setConstructor(FNMATCH); + + size_t archfound = pattern.find_last_of(':'); + std::string arch = "native"; + if (archfound != std::string::npos) { + arch = pattern.substr(archfound+1); + if (arch.find_first_of(isfnmatch) == std::string::npos) + pattern.erase(archfound); + else + arch = "native"; + } + + if (unlikely(Cache.GetPkgCache() == 0)) + return false; + + APT::CacheFilter::PackageNameMatchesFnmatch filter(pattern); + + bool found = false; + for (pkgCache::GrpIterator Grp = Cache.GetPkgCache()->GrpBegin(); Grp.end() == false; ++Grp) { + if (filter(Grp) == false) + continue; + pkgCache::PkgIterator Pkg = Grp.FindPkg(arch); + if (Pkg.end() == true) { + if (archfound == std::string::npos) { + std::vector<std::string> archs = APT::Configuration::getArchitectures(); + for (std::vector<std::string>::const_iterator a = archs.begin(); + a != archs.end() && Pkg.end() != true; ++a) + Pkg = Grp.FindPkg(*a); + } + if (Pkg.end() == true) + continue; + } + + pci->insert(Pkg); + helper.showRegExSelection(Pkg, pattern); + found = true; + } + + if (found == false) { + helper.canNotFindRegEx(pci, Cache, pattern); + pci->setConstructor(UNKNOWN); + return false; + } + + if (wasEmpty == false && pci->getConstructor() != UNKNOWN) + pci->setConstructor(UNKNOWN); + + return true; +} + /*}}}*/ // FromName - Returns the package defined by this string /*{{{*/ pkgCache::PkgIterator PackageContainerInterface::FromName(pkgCacheFile &Cache, std::string const &str, CacheSetHelper &helper) { @@ -239,6 +302,7 @@ bool PackageContainerInterface::FromString(PackageContainerInterface * const pci if (FromGroup(pci, Cache, str, helper) == false && FromTask(pci, Cache, str, helper) == false && + FromFnmatch(pci, Cache, str, helper) == false && FromRegEx(pci, Cache, str, helper) == false) { helper.canNotFindPackage(pci, Cache, str); diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index d7328d705..29103aad9 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -131,13 +131,14 @@ public: virtual bool empty() const = 0; virtual void clear() = 0; - enum Constructor { UNKNOWN, REGEX, TASK }; + enum Constructor { UNKNOWN, REGEX, TASK, FNMATCH }; virtual void setConstructor(Constructor const &con) = 0; virtual Constructor getConstructor() const = 0; static bool FromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static bool FromRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper); + static bool FromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static bool FromGroup(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static bool FromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper); static bool FromCommandLine(PackageContainerInterface * const pci, pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper); @@ -259,6 +260,16 @@ public: /*{{{*/ return FromRegEx(Cache, pattern, helper); } + static PackageContainer FromFnmatch(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) { + PackageContainer cont(FNMATCH); + PackageContainerInterface::FromFnmatch(&cont, Cache, pattern, helper); + return cont; + } + static PackageContainer FromFnMatch(pkgCacheFile &Cache, std::string const &pattern) { + CacheSetHelper helper; + return FromFnmatch(Cache, pattern, helper); + } + /** \brief returns a package specified by a string \param Cache the package is in diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index 75d02cad4..8cef80368 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -38,6 +38,42 @@ CommandLine::~CommandLine() delete [] FileList; } /*}}}*/ +// CommandLine::GetCommand - return the first non-option word /*{{{*/ +char const * CommandLine::GetCommand(Dispatch const * const Map, + unsigned int const argc, char const * const * const argv) +{ + // if there is a -- on the line there must be the word we search for around it + // as -- marks the end of the options, just not sure if the command can be + // considered an option or not, so accept both + for (size_t i = 1; i < argc; ++i) + { + if (strcmp(argv[i], "--") != 0) + continue; + ++i; + if (i < argc) + for (size_t j = 0; Map[j].Match != NULL; ++j) + if (strcmp(argv[i], Map[j].Match) == 0) + return Map[j].Match; + i -= 2; + if (i != 0) + for (size_t j = 0; Map[j].Match != NULL; ++j) + if (strcmp(argv[i], Map[j].Match) == 0) + return Map[j].Match; + return NULL; + } + // no --, so search for the first word matching a command + // FIXME: How like is it that an option parameter will be also a valid Match ? + for (size_t i = 1; i < argc; ++i) + { + if (*(argv[i]) == '-') + continue; + for (size_t j = 0; Map[j].Match != NULL; ++j) + if (strcmp(argv[i], Map[j].Match) == 0) + return Map[j].Match; + } + return NULL; +} + /*}}}*/ // CommandLine::Parse - Main action member /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -390,3 +426,15 @@ void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * co _config->Set("CommandLine::AsString", cmdline); } /*}}}*/ +CommandLine::Args CommandLine::MakeArgs(char ShortOpt, char const *LongOpt, char const *ConfName, unsigned long Flags)/*{{{*/ +{ + /* In theory, this should be a constructor for CommandLine::Args instead, + but this breaks compatibility as gcc thinks this is a c++11 initializer_list */ + CommandLine::Args arg; + arg.ShortOpt = ShortOpt; + arg.LongOpt = LongOpt; + arg.ConfName = ConfName; + arg.Flags = Flags; + return arg; +} + /*}}}*/ diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h index 9f505fd41..180276633 100644 --- a/apt-pkg/contrib/cmndline.h +++ b/apt-pkg/contrib/cmndline.h @@ -83,6 +83,12 @@ class CommandLine unsigned int FileSize() const; bool DispatchArg(Dispatch *List,bool NoMatch = true); + static char const * GetCommand(Dispatch const * const Map, + unsigned int const argc, char const * const * const argv); + + static CommandLine::Args MakeArgs(char ShortOpt, char const *LongOpt, + char const *ConfName, unsigned long Flags); + CommandLine(Args *AList,Configuration *Conf); ~CommandLine(); }; diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index df02c3499..d06637155 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1291,6 +1291,18 @@ bool CheckDomainList(const string &Host,const string &List) return false; } /*}}}*/ +// strv_length - Return the length of a NULL-terminated string array /*{{{*/ +// --------------------------------------------------------------------- +/* */ +size_t strv_length(const char **str_array) +{ + size_t i; + for (i=0; str_array[i] != NULL; i++) + /* nothing */ + ; + return i; +} + // DeEscapeString - unescape (\0XX and \xXX) from a string /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index e92f91dc0..530896141 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -108,6 +108,10 @@ inline int stringcasecmp(std::string::const_iterator A,std::string::const_iterat APT_MKSTRCMP2(stringcmp,stringcmp); APT_MKSTRCMP2(stringcasecmp,stringcasecmp); +// Return the length of a NULL-terminated string array +size_t strv_length(const char **str_array); + + inline const char *DeNull(const char *s) {return (s == 0?"(null)":s);}; class URI diff --git a/apt-private/acqprogress.cc b/apt-private/acqprogress.cc new file mode 100644 index 000000000..af2d0f461 --- /dev/null +++ b/apt-private/acqprogress.cc @@ -0,0 +1,309 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: acqprogress.cc,v 1.24 2003/04/27 01:56:48 doogie Exp $ +/* ###################################################################### + + Acquire Progress - Command line progress meter + + ##################################################################### */ + /*}}}*/ +// Include files /*{{{*/ +#include<config.h> + +#include <apt-pkg/acquire-item.h> +#include <apt-pkg/acquire-worker.h> +#include <apt-pkg/configuration.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/error.h> + +#include <stdio.h> +#include <signal.h> +#include <iostream> +#include <unistd.h> + +#include "acqprogress.h" +#include <apti18n.h> + /*}}}*/ + +using namespace std; + +// AcqTextStatus::AcqTextStatus - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) : + ScreenWidth(ScreenWidth), ID(0), Quiet(Quiet) +{ + BlankLine[0] = 0; +} + /*}}}*/ +// AcqTextStatus::Start - Downloading has started /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void AcqTextStatus::Start() +{ + pkgAcquireStatus::Start(); + BlankLine[0] = 0; + ID = 1; +}; + /*}}}*/ +// AcqTextStatus::IMSHit - Called when an item got a HIT response /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc &Itm) +{ + if (Quiet > 1) + return; + + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r'; + + cout << _("Hit ") << Itm.Description; + if (Itm.Owner->FileSize != 0) + cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]"; + cout << endl; + Update = true; +}; + /*}}}*/ +// AcqTextStatus::Fetch - An item has started to download /*{{{*/ +// --------------------------------------------------------------------- +/* This prints out the short description and the expected size */ +void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm) +{ + Update = true; + if (Itm.Owner->Complete == true) + return; + + Itm.Owner->ID = ID++; + + if (Quiet > 1) + return; + + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r'; + + cout << _("Get:") << Itm.Owner->ID << ' ' << Itm.Description; + if (Itm.Owner->FileSize != 0) + cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]"; + cout << endl; +}; + /*}}}*/ +// AcqTextStatus::Done - Completed a download /*{{{*/ +// --------------------------------------------------------------------- +/* We don't display anything... */ +void AcqTextStatus::Done(pkgAcquire::ItemDesc &Itm) +{ + Update = true; +}; + /*}}}*/ +// AcqTextStatus::Fail - Called when an item fails to download /*{{{*/ +// --------------------------------------------------------------------- +/* We print out the error text */ +void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm) +{ + if (Quiet > 1) + return; + + // Ignore certain kinds of transient failures (bad code) + if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) + return; + + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r'; + + if (Itm.Owner->Status == pkgAcquire::Item::StatDone) + { + cout << _("Ign ") << Itm.Description << endl; + } + else + { + cout << _("Err ") << Itm.Description << endl; + cout << " " << Itm.Owner->ErrorText << endl; + } + + Update = true; +}; + /*}}}*/ +// AcqTextStatus::Stop - Finished downloading /*{{{*/ +// --------------------------------------------------------------------- +/* This prints out the bytes downloaded and the overall average line + speed */ +void AcqTextStatus::Stop() +{ + pkgAcquireStatus::Stop(); + if (Quiet > 1) + return; + + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r' << flush; + + if (FetchedBytes != 0 && _error->PendingError() == false) + ioprintf(cout,_("Fetched %sB in %s (%sB/s)\n"), + SizeToStr(FetchedBytes).c_str(), + TimeToStr(ElapsedTime).c_str(), + SizeToStr(CurrentCPS).c_str()); +} + /*}}}*/ +// AcqTextStatus::Pulse - Regular event pulse /*{{{*/ +// --------------------------------------------------------------------- +/* This draws the current progress. Each line has an overall percent + meter and a per active item status meter along with an overall + bandwidth and ETA indicator. */ +bool AcqTextStatus::Pulse(pkgAcquire *Owner) +{ + pkgAcquireStatus::Pulse(Owner); + + if (Quiet > 0) + return true; + + enum {Long = 0,Medium,Short} Mode = Medium; + + char Buffer[sizeof(BlankLine)]; + char *End = Buffer + sizeof(Buffer); + char *S = Buffer; + if (ScreenWidth >= sizeof(Buffer)) + ScreenWidth = sizeof(Buffer)-1; + + // Put in the percent done + sprintf(S,"%.0f%%",((CurrentBytes + CurrentItems)*100.0)/(TotalBytes+TotalItems)); + + bool Shown = false; + for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0; + I = Owner->WorkerStep(I)) + { + S += strlen(S); + + // There is no item running + if (I->CurrentItem == 0) + { + if (I->Status.empty() == false) + { + snprintf(S,End-S," [%s]",I->Status.c_str()); + Shown = true; + } + + continue; + } + + Shown = true; + + // Add in the short description + if (I->CurrentItem->Owner->ID != 0) + snprintf(S,End-S," [%lu %s",I->CurrentItem->Owner->ID, + I->CurrentItem->ShortDesc.c_str()); + else + snprintf(S,End-S," [%s",I->CurrentItem->ShortDesc.c_str()); + S += strlen(S); + + // Show the short mode string + if (I->CurrentItem->Owner->Mode != 0) + { + snprintf(S,End-S," %s",I->CurrentItem->Owner->Mode); + S += strlen(S); + } + + // Add the current progress + if (Mode == Long) + snprintf(S,End-S," %llu",I->CurrentSize); + else + { + if (Mode == Medium || I->TotalSize == 0) + snprintf(S,End-S," %sB",SizeToStr(I->CurrentSize).c_str()); + } + S += strlen(S); + + // Add the total size and percent + if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false) + { + if (Mode == Short) + snprintf(S,End-S," %.0f%%", + (I->CurrentSize*100.0)/I->TotalSize); + else + snprintf(S,End-S,"/%sB %.0f%%",SizeToStr(I->TotalSize).c_str(), + (I->CurrentSize*100.0)/I->TotalSize); + } + S += strlen(S); + snprintf(S,End-S,"]"); + } + + // Show something.. + if (Shown == false) + snprintf(S,End-S,_(" [Working]")); + + /* Put in the ETA and cps meter, block off signals to prevent strangeness + during resizing */ + sigset_t Sigs,OldSigs; + sigemptyset(&Sigs); + sigaddset(&Sigs,SIGWINCH); + sigprocmask(SIG_BLOCK,&Sigs,&OldSigs); + + if (CurrentCPS != 0) + { + char Tmp[300]; + unsigned long long ETA = (TotalBytes - CurrentBytes)/CurrentCPS; + sprintf(Tmp," %sB/s %s",SizeToStr(CurrentCPS).c_str(),TimeToStr(ETA).c_str()); + unsigned int Len = strlen(Buffer); + unsigned int LenT = strlen(Tmp); + if (Len + LenT < ScreenWidth) + { + memset(Buffer + Len,' ',ScreenWidth - Len); + strcpy(Buffer + ScreenWidth - LenT,Tmp); + } + } + Buffer[ScreenWidth] = 0; + BlankLine[ScreenWidth] = 0; + sigprocmask(SIG_SETMASK,&OldSigs,0); + + // Draw the current status + if (_config->FindB("Apt::Color", false) == true) + cout << _config->Find("APT::Color::Yellow"); + if (strlen(Buffer) == strlen(BlankLine)) + cout << '\r' << Buffer << flush; + else + cout << '\r' << BlankLine << '\r' << Buffer << flush; + if (_config->FindB("Apt::Color", false) == true) + cout << _config->Find("APT::Color::Neutral"); + + memset(BlankLine,' ',strlen(Buffer)); + BlankLine[strlen(Buffer)] = 0; + + Update = false; + + return true; +} + /*}}}*/ +// AcqTextStatus::MediaChange - Media need to be swapped /*{{{*/ +// --------------------------------------------------------------------- +/* Prompt for a media swap */ +bool AcqTextStatus::MediaChange(string Media,string Drive) +{ + // If we do not output on a terminal and one of the options to avoid user + // interaction is given, we assume that no user is present who could react + // on your media change request + if (isatty(STDOUT_FILENO) != 1 && Quiet >= 2 && + (_config->FindB("APT::Get::Assume-Yes",false) == true || + _config->FindB("APT::Get::Force-Yes",false) == true || + _config->FindB("APT::Get::Trivial-Only",false) == true)) + + return false; + + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r'; + ioprintf(cout,_("Media change: please insert the disc labeled\n" + " '%s'\n" + "in the drive '%s' and press enter\n"), + Media.c_str(),Drive.c_str()); + + char C = 0; + bool bStatus = true; + while (C != '\n' && C != '\r') + { + int len = read(STDIN_FILENO,&C,1); + if(C == 'c' || len <= 0) + bStatus = false; + } + + if(bStatus) + Update = true; + return bStatus; +} + /*}}}*/ diff --git a/apt-private/acqprogress.h b/apt-private/acqprogress.h new file mode 100644 index 000000000..e47bfb72d --- /dev/null +++ b/apt-private/acqprogress.h @@ -0,0 +1,38 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Acquire Progress - Command line progress meter + + ##################################################################### */ + /*}}}*/ +#ifndef ACQPROGRESS_H +#define ACQPROGRESS_H + +#include <apt-pkg/acquire.h> + +#include <string> + +class AcqTextStatus : public pkgAcquireStatus +{ + unsigned int &ScreenWidth; + char BlankLine[1024]; + unsigned long ID; + unsigned long Quiet; + + public: + + virtual bool MediaChange(std::string Media,std::string Drive); + virtual void IMSHit(pkgAcquire::ItemDesc &Itm); + virtual void Fetch(pkgAcquire::ItemDesc &Itm); + virtual void Done(pkgAcquire::ItemDesc &Itm); + virtual void Fail(pkgAcquire::ItemDesc &Itm); + virtual void Start(); + virtual void Stop(); + + bool Pulse(pkgAcquire *Owner); + + AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet); +}; + +#endif diff --git a/apt-private/makefile b/apt-private/makefile new file mode 100644 index 000000000..8feb1ce6c --- /dev/null +++ b/apt-private/makefile @@ -0,0 +1,28 @@ +# -*- make -*- +BASE=.. +SUBDIR=apt-private + +# Header location +HEADER_TARGETDIRS = apt-private + +# Bring in the default rules +include ../buildlib/defaults.mak + +# The library name and version (indirectly used from init.h) +include ../buildlib/libversion.mak + +# The library name +LIBRARY=apt-private +MAJOR=0.0 +MINOR=0 +SLIBS=$(PTHREADLIB) -lapt-pkg + +PRIVATES=list install output cachefile cacheset update upgrade cmndline moo search show main +SOURCE += $(foreach private, $(PRIVATES), private-$(private).cc) +HEADERS += $(foreach private, $(PRIVATES), private-$(private).h) + +SOURCE+= acqprogress.cc +HEADERS+= acqprogress.h private-cacheset.h + +HEADERS := $(addprefix apt-private/,$(HEADERS)) +include $(LIBRARY_H) diff --git a/apt-private/private-cachefile.cc b/apt-private/private-cachefile.cc new file mode 100644 index 000000000..25f65ef09 --- /dev/null +++ b/apt-private/private-cachefile.cc @@ -0,0 +1,109 @@ +// Include files /*{{{*/ +#include<config.h> + +#include <apt-pkg/algorithms.h> +#include <apt-pkg/error.h> + +#include <cstdlib> + +#include "private-output.h" +#include "private-cachefile.h" + +#include <apti18n.h> + /*}}}*/ + +using namespace std; + +// CacheFile::NameComp - QSort compare by name /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgCache *CacheFile::SortCache = 0; +int CacheFile::NameComp(const void *a,const void *b) +{ + if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0) + return *(pkgCache::Package **)a - *(pkgCache::Package **)b; + + const pkgCache::Package &A = **(pkgCache::Package **)a; + const pkgCache::Package &B = **(pkgCache::Package **)b; + + return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name); +} + /*}}}*/ +// CacheFile::Sort - Sort by name /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void CacheFile::Sort() +{ + delete [] List; + List = new pkgCache::Package *[Cache->Head().PackageCount]; + memset(List,0,sizeof(*List)*Cache->Head().PackageCount); + pkgCache::PkgIterator I = Cache->PkgBegin(); + for (;I.end() != true; ++I) + List[I->ID] = I; + + SortCache = *this; + qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp); +} + /*}}}*/ +// CacheFile::CheckDeps - Open the cache file /*{{{*/ +// --------------------------------------------------------------------- +/* This routine generates the caches and then opens the dependency cache + and verifies that the system is OK. */ +bool CacheFile::CheckDeps(bool AllowBroken) +{ + bool FixBroken = _config->FindB("APT::Get::Fix-Broken",false); + + if (_error->PendingError() == true) + return false; + + // Check that the system is OK + if (DCache->DelCount() != 0 || DCache->InstCount() != 0) + return _error->Error("Internal error, non-zero counts"); + + // Apply corrections for half-installed packages + if (pkgApplyStatus(*DCache) == false) + return false; + + if (_config->FindB("APT::Get::Fix-Policy-Broken",false) == true) + { + FixBroken = true; + if ((DCache->PolicyBrokenCount() > 0)) + { + // upgrade all policy-broken packages with ForceImportantDeps=True + for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); ++I) + if ((*DCache)[I].NowPolicyBroken() == true) + DCache->MarkInstall(I,true,0, false, true); + } + } + + // Nothing is broken + if (DCache->BrokenCount() == 0 || AllowBroken == true) + return true; + + // Attempt to fix broken things + if (FixBroken == true) + { + c1out << _("Correcting dependencies...") << flush; + if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0) + { + c1out << _(" failed.") << endl; + ShowBroken(c1out,*this,true); + + return _error->Error(_("Unable to correct dependencies")); + } + if (pkgMinimizeUpgrade(*DCache) == false) + return _error->Error(_("Unable to minimize the upgrade set")); + + c1out << _(" Done") << endl; + } + else + { + c1out << _("You might want to run 'apt-get -f install' to correct these.") << endl; + ShowBroken(c1out,*this,true); + + return _error->Error(_("Unmet dependencies. Try using -f.")); + } + + return true; +} + /*}}}*/ diff --git a/apt-private/private-cachefile.h b/apt-private/private-cachefile.h new file mode 100644 index 000000000..f24d93020 --- /dev/null +++ b/apt-private/private-cachefile.h @@ -0,0 +1,51 @@ +#ifndef APT_PRIVATE_CACHEFILE_H +#define APT_PRIVATE_CACHEFILE_H + +#include <apt-pkg/cachefile.h> +#include <apt-pkg/progress.h> + + +// class CacheFile - Cover class for some dependency cache functions /*{{{*/ +// --------------------------------------------------------------------- +/* */ +class CacheFile : public pkgCacheFile +{ + static pkgCache *SortCache; + static int NameComp(const void *a,const void *b); + + public: + pkgCache::Package **List; + + void Sort(); + bool CheckDeps(bool AllowBroken = false); + bool BuildCaches(bool WithLock = true) + { + OpTextProgress Prog(*_config); + if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false) + return false; + return true; + } + bool Open(bool WithLock = true) + { + OpTextProgress Prog(*_config); + if (pkgCacheFile::Open(&Prog,WithLock) == false) + return false; + Sort(); + + return true; + }; + bool OpenForInstall() + { + if (_config->FindB("APT::Get::Print-URIs") == true) + return Open(false); + else + return Open(true); + } + CacheFile() : List(0) {}; + ~CacheFile() { + delete[] List; + } +}; + /*}}}*/ + +#endif diff --git a/apt-private/private-cacheset.cc b/apt-private/private-cacheset.cc new file mode 100644 index 000000000..6fb224010 --- /dev/null +++ b/apt-private/private-cacheset.cc @@ -0,0 +1,63 @@ +#include <apt-pkg/cachefile.h> +#include <apt-pkg/pkgcache.h> +#include <apt-pkg/depcache.h> +#include <apt-pkg/strutl.h> + +#include "private-cacheset.h" + +bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, + LocalitySortedVersionSet &output_set, + OpProgress &progress) +{ + Matcher null_matcher = Matcher(); + return GetLocalitySortedVersionSet(CacheFile, output_set, + null_matcher, progress); +} + +bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, + LocalitySortedVersionSet &output_set, + Matcher &matcher, + OpProgress &progress) +{ + pkgCache *Cache = CacheFile.GetPkgCache(); + pkgDepCache *DepCache = CacheFile.GetDepCache(); + + int Done=0; + progress.SubProgress(Cache->Head().PackageCount, _("Sorting")); + for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P) + { + if (Done%500 == 0) + progress.Progress(Done); + Done++; + + if ((matcher)(P) == false) + continue; + + // exclude virtual pkgs + if (P.VersionList() == 0) + continue; + pkgDepCache::StateCache &state = (*DepCache)[P]; + if (_config->FindB("APT::Cmd::Installed") == true) + { + if (P.CurrentVer() != NULL) + { + output_set.insert(P.CurrentVer()); + } + } + else if (_config->FindB("APT::Cmd::Upgradable") == true) + { + if(P.CurrentVer() && state.Upgradable()) + { + pkgPolicy *policy = CacheFile.GetPolicy(); + output_set.insert(policy->GetCandidateVer(P)); + } + } + else + { + pkgPolicy *policy = CacheFile.GetPolicy(); + output_set.insert(policy->GetCandidateVer(P)); + } + } + progress.Done(); + return true; +} diff --git a/apt-private/private-cacheset.h b/apt-private/private-cacheset.h new file mode 100644 index 000000000..15b531e9d --- /dev/null +++ b/apt-private/private-cacheset.h @@ -0,0 +1,265 @@ +#ifndef APT_PRIVATE_CACHESET_H +#define APT_PRIVATE_CACHESET_H + +#include <apt-pkg/cachefile.h> +#include <apt-pkg/cacheset.h> +#include <apt-pkg/sptr.h> + +#include <algorithm> +#include <vector> + +#include "private-output.h" + +#include <apti18n.h> + +struct VersionSortDescriptionLocality +{ + bool operator () (const pkgCache::VerIterator &v_lhs, + const pkgCache::VerIterator &v_rhs) + { + pkgCache::DescFile *A = v_lhs.TranslatedDescription().FileList(); + pkgCache::DescFile *B = v_rhs.TranslatedDescription().FileList(); + if (A == 0 && B == 0) + return false; + + if (A == 0) + return true; + + if (B == 0) + return false; + + if (A->File == B->File) + return A->Offset < B->Offset; + + return A->File < B->File; + } +}; + +// sorted by locality which makes iterating much faster +typedef APT::VersionContainer< + std::set<pkgCache::VerIterator, + VersionSortDescriptionLocality> > LocalitySortedVersionSet; + +class Matcher { +public: + virtual bool operator () (const pkgCache::PkgIterator &P) { + return true;}; +}; + +// FIXME: add default argument for OpProgress (or overloaded function) +bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, + LocalitySortedVersionSet &output_set, + Matcher &matcher, + OpProgress &progress); +bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, + LocalitySortedVersionSet &output_set, + OpProgress &progress); + + +// CacheSetHelper saving virtual packages /*{{{*/ +class CacheSetHelperVirtuals: public APT::CacheSetHelper { +public: + APT::PackageSet virtualPkgs; + + virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + virtualPkgs.insert(Pkg); + return CacheSetHelper::canNotFindCandidateVer(Cache, Pkg); + } + + virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + virtualPkgs.insert(Pkg); + return CacheSetHelper::canNotFindNewestVer(Cache, Pkg); + } + + virtual void canNotFindAllVer(APT::VersionContainerInterface * vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + virtualPkgs.insert(Pkg); + CacheSetHelper::canNotFindAllVer(vci, Cache, Pkg); + } + + CacheSetHelperVirtuals(bool const ShowErrors = true, GlobalError::MsgType const &ErrorType = GlobalError::NOTICE) : CacheSetHelper(ShowErrors, ErrorType) {} +}; + /*}}}*/ + +// CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/ +class CacheSetHelperAPTGet : public APT::CacheSetHelper { + /** \brief stream message should be printed to */ + std::ostream &out; + /** \brief were things like Task or RegEx used to select packages? */ + bool explicitlyNamed; + + APT::PackageSet virtualPkgs; + +public: + std::list<std::pair<pkgCache::VerIterator, std::string> > selectedByRelease; + + CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) { + explicitlyNamed = true; + } + + virtual void showTaskSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) { + ioprintf(out, _("Note, selecting '%s' for task '%s'\n"), + Pkg.FullName(true).c_str(), pattern.c_str()); + explicitlyNamed = false; + } + virtual void showRegExSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) { + ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"), + Pkg.FullName(true).c_str(), pattern.c_str()); + explicitlyNamed = false; + } + virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver, + std::string const &ver, bool const verIsRel) { + if (ver == Ver.VerStr()) + return; + selectedByRelease.push_back(make_pair(Ver, ver)); + } + + bool showVirtualPackageErrors(pkgCacheFile &Cache) { + if (virtualPkgs.empty() == true) + return true; + for (APT::PackageSet::const_iterator Pkg = virtualPkgs.begin(); + Pkg != virtualPkgs.end(); ++Pkg) { + if (Pkg->ProvidesList != 0) { + ioprintf(c1out,_("Package %s is a virtual package provided by:\n"), + Pkg.FullName(true).c_str()); + + pkgCache::PrvIterator I = Pkg.ProvidesList(); + unsigned short provider = 0; + for (; I.end() == false; ++I) { + pkgCache::PkgIterator Pkg = I.OwnerPkg(); + + if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) { + c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr(); + if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false) + c1out << _(" [Installed]"); + c1out << std::endl; + ++provider; + } + } + // if we found no candidate which provide this package, show non-candidates + if (provider == 0) + for (I = Pkg.ProvidesList(); I.end() == false; ++I) + c1out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr() + << _(" [Not candidate version]") << std::endl; + else + out << _("You should explicitly select one to install.") << std::endl; + } else { + ioprintf(c1out, + _("Package %s is not available, but is referred to by another package.\n" + "This may mean that the package is missing, has been obsoleted, or\n" + "is only available from another source\n"),Pkg.FullName(true).c_str()); + + std::string List; + std::string VersionsList; + SPtrArray<bool> Seen = new bool[Cache.GetPkgCache()->Head().PackageCount]; + memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen)); + for (pkgCache::DepIterator Dep = Pkg.RevDependsList(); + Dep.end() == false; ++Dep) { + if (Dep->Type != pkgCache::Dep::Replaces) + continue; + if (Seen[Dep.ParentPkg()->ID] == true) + continue; + Seen[Dep.ParentPkg()->ID] = true; + List += Dep.ParentPkg().FullName(true) + " "; + //VersionsList += std::string(Dep.ParentPkg().CurVersion) + "\n"; ??? + } + ShowList(c1out,_("However the following packages replace it:"),List,VersionsList); + } + c1out << std::endl; + } + return false; + } + + virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE); + if (verset.empty() == false) + return *(verset.begin()); + else if (ShowError == true) { + _error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str()); + virtualPkgs.insert(Pkg); + } + return pkgCache::VerIterator(Cache, 0); + } + + virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + if (Pkg->ProvidesList != 0) + { + APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST); + if (verset.empty() == false) + return *(verset.begin()); + if (ShowError == true) + ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str()); + } + else + { + pkgCache::GrpIterator Grp = Pkg.Group(); + pkgCache::PkgIterator P = Grp.PackageList(); + for (; P.end() != true; P = Grp.NextPkg(P)) + { + if (P == Pkg) + continue; + if (P->CurrentVer != 0) { + // TRANSLATORS: Note, this is not an interactive question + ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"), + Pkg.FullName(true).c_str(), P.FullName(true).c_str()); + break; + } + } + if (P.end() == true) + ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str()); + } + return pkgCache::VerIterator(Cache, 0); + } + + APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg, + APT::VersionSet::Version const &select) { + /* This is a pure virtual package and there is a single available + candidate providing it. */ + if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0) + return APT::VersionSet(); + + pkgCache::PkgIterator Prov; + bool found_one = false; + for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) { + pkgCache::VerIterator const PVer = P.OwnerVer(); + pkgCache::PkgIterator const PPkg = PVer.ParentPkg(); + + /* Ignore versions that are not a candidate. */ + if (Cache[PPkg].CandidateVer != PVer) + continue; + + if (found_one == false) { + Prov = PPkg; + found_one = true; + } else if (PPkg != Prov) { + // same group, so it's a foreign package + if (PPkg->Group == Prov->Group) { + // do we already have the requested arch? + if (strcmp(Pkg.Arch(), Prov.Arch()) == 0 || + strcmp(Prov.Arch(), "all") == 0 || + unlikely(strcmp(PPkg.Arch(), Prov.Arch()) == 0)) // packages have only on candidate, but just to be sure + continue; + // see which architecture we prefer more and switch to it + std::vector<std::string> archs = APT::Configuration::getArchitectures(); + if (std::find(archs.begin(), archs.end(), PPkg.Arch()) < std::find(archs.begin(), archs.end(), Prov.Arch())) + Prov = PPkg; + continue; + } + found_one = false; // we found at least two + break; + } + } + + if (found_one == true) { + ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"), + Prov.FullName(true).c_str(), Pkg.FullName(true).c_str()); + return APT::VersionSet::FromPackage(Cache, Prov, select, *this); + } + return APT::VersionSet(); + } + + inline bool allPkgNamedExplicitly() const { return explicitlyNamed; } + +}; + /*}}}*/ + +#endif diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc new file mode 100644 index 000000000..aceb865d5 --- /dev/null +++ b/apt-private/private-cmndline.cc @@ -0,0 +1,268 @@ +// Include Files /*{{{*/ +#include <config.h> + +#include <apt-pkg/cmndline.h> +#include <apt-pkg/configuration.h> + +#include <vector> + +#include <stdarg.h> +#include <string.h> + +#include "private-cmndline.h" + +#include <apti18n.h> + /*}}}*/ + +bool strcmp_match_in_list(char const * const Cmd, ...) /*{{{*/ +{ + va_list args; + bool found = false; + va_start(args, Cmd); + char const * Match = NULL; + while ((Match = va_arg(args, char const *)) != NULL) + { + if (strcmp(Cmd, Match) != 0) + continue; + found = true; + break; + } + va_end(args); + return found; +} + /*}}}*/ +#define addArg(w,x,y,z) Args.push_back(CommandLine::MakeArgs(w,x,y,z)) +#define CmdMatches(...) strcmp_match_in_list(Cmd, __VA_ARGS__, NULL) +bool addArgumentsAPTCache(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/ +{ + if (CmdMatches("depends", "rdepends", "xvcg", "dotty")) + { + addArg('i', "important", "APT::Cache::Important", 0); + addArg(0, "installed", "APT::Cache::Installed", 0); + addArg(0, "pre-depends", "APT::Cache::ShowPre-Depends", 0); + addArg(0, "depends", "APT::Cache::ShowDepends", 0); + addArg(0, "recommends", "APT::Cache::ShowRecommends", 0); + addArg(0, "suggests", "APT::Cache::ShowSuggests", 0); + addArg(0, "replaces", "APT::Cache::ShowReplaces", 0); + addArg(0, "breaks", "APT::Cache::ShowBreaks", 0); + addArg(0, "conflicts", "APT::Cache::ShowConflicts", 0); + addArg(0, "enhances", "APT::Cache::ShowEnhances", 0); + addArg(0, "recurse", "APT::Cache::RecurseDepends", 0); + } + else if (CmdMatches("search")) + { + addArg('n', "names-only", "APT::Cache::NamesOnly", 0); + addArg('f', "full", "APT::Cache::ShowFull", 0); + } + else if (CmdMatches("show")) + { + addArg('a', "all-versions", "APT::Cache::AllVersions", 0); + } + else if (CmdMatches("pkgnames")) + { + addArg(0, "all-names", "APT::Cache::AllNames", 0); + } + else if (CmdMatches("gencaches", "showsrc", "showpkg", "stats", "dump", + "dumpavail", "unmet", "showauto", "policy", "madison")) + ; + else + return false; + + // FIXME: move to the correct command(s) + addArg('g', "generate", "APT::Cache::Generate", 0); + addArg('t', "target-release", "APT::Default-Release", CommandLine::HasArg); + addArg('t', "default-release", "APT::Default-Release", CommandLine::HasArg); + + addArg('p', "pkg-cache", "Dir::Cache::pkgcache", CommandLine::HasArg); + addArg('s', "src-cache", "Dir::Cache::srcpkgcache", CommandLine::HasArg); + return true; +} + /*}}}*/ +bool addArgumentsAPTCDROM(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/ +{ + if (CmdMatches("add", "ident") == false) + return false; + + // FIXME: move to the correct command(s) + addArg(0, "auto-detect", "Acquire::cdrom::AutoDetect", CommandLine::Boolean); + addArg('d', "cdrom", "Acquire::cdrom::mount", CommandLine::HasArg); + addArg('r', "rename", "APT::CDROM::Rename", 0); + addArg('m', "no-mount", "APT::CDROM::NoMount", 0); + addArg('f', "fast", "APT::CDROM::Fast", 0); + addArg('n', "just-print", "APT::CDROM::NoAct", 0); + addArg('n', "recon", "APT::CDROM::NoAct", 0); + addArg('n', "no-act", "APT::CDROM::NoAct", 0); + addArg('a', "thorough", "APT::CDROM::Thorough", 0); + return true; +} + /*}}}*/ +bool addArgumentsAPTConfig(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/ +{ + if (CmdMatches("dump")) + { + addArg(0,"empty","APT::Config::Dump::EmptyValue",CommandLine::Boolean); + addArg(0,"format","APT::Config::Dump::Format",CommandLine::HasArg); + } + else if (CmdMatches("shell")) + ; + else + return false; + + return true; +} + /*}}}*/ +bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/ +{ + if (CmdMatches("install", "remove", "purge", "upgrade", "dist-upgrade", + "deselect-upgrade", "autoremove")) + { + addArg(0, "dpkg-progress", "DpkgPM::Progress", 0); + addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0); + addArg(0, "purge", "APT::Get::Purge", 0); + addArg('V',"verbose-versions","APT::Get::Show-Versions",0); + addArg(0, "auto-remove", "APT::Get::AutomaticRemove", 0); + addArg(0, "reinstall", "APT::Get::ReInstall", 0); + addArg(0, "solver", "APT::Solver", CommandLine::HasArg); + if (CmdMatches("upgrade")) + { + addArg(0, "allow-new", "APT::Get::UpgradeAllowNew", 0); + } + } + else if (CmdMatches("update")) + { + addArg(0, "list-cleanup", "APT::Get::List-Cleanup", 0); + } + else if (CmdMatches("source")) + { + addArg('b', "compile", "APT::Get::Compile", 0); + addArg('b', "build", "APT::Get::Compile", 0); + addArg(0, "diff-only", "APT::Get::Diff-Only", 0); + addArg(0, "debian-only", "APT::Get::Diff-Only", 0); + addArg(0, "tar-only", "APT::Get::Tar-Only", 0); + addArg(0, "dsc-only", "APT::Get::Dsc-Only", 0); + } + else if (CmdMatches("build-dep")) + { + addArg('a', "host-architecture", "APT::Get::Host-Architecture", CommandLine::HasArg); + addArg(0, "solver", "APT::Solver", CommandLine::HasArg); + } + else if (CmdMatches("clean", "autoclean", "check", "download", "changelog") || + CmdMatches("markauto", "unmarkauto")) // deprecated commands + ; + else if (CmdMatches("moo")) + addArg(0, "color", "APT::Moo::Color", 0); + + if (CmdMatches("install", "remove", "purge", "upgrade", "dist-upgrade", + "deselect-upgrade", "autoremove", "clean", "autoclean", "check", + "build-dep")) + { + addArg('s', "simulate", "APT::Get::Simulate", 0); + addArg('s', "just-print", "APT::Get::Simulate", 0); + addArg('s', "recon", "APT::Get::Simulate", 0); + addArg('s', "dry-run", "APT::Get::Simulate", 0); + addArg('s', "no-act", "APT::Get::Simulate", 0); + } + + // FIXME: move to the correct command(s) + addArg('d',"download-only","APT::Get::Download-Only",0); + addArg('y',"yes","APT::Get::Assume-Yes",0); + addArg('y',"assume-yes","APT::Get::Assume-Yes",0); + addArg(0,"assume-no","APT::Get::Assume-No",0); + addArg('u',"show-upgraded","APT::Get::Show-Upgraded",0); + addArg('m',"ignore-missing","APT::Get::Fix-Missing",0); + addArg('t',"target-release","APT::Default-Release",CommandLine::HasArg); + addArg('t',"default-release","APT::Default-Release",CommandLine::HasArg); + addArg(0,"download","APT::Get::Download",0); + addArg(0,"fix-missing","APT::Get::Fix-Missing",0); + addArg(0,"ignore-hold","APT::Ignore-Hold",0); + addArg(0,"upgrade","APT::Get::upgrade",0); + addArg(0,"only-upgrade","APT::Get::Only-Upgrade",0); + addArg(0,"force-yes","APT::Get::force-yes",0); + addArg(0,"print-uris","APT::Get::Print-URIs",0); + addArg(0,"trivial-only","APT::Get::Trivial-Only",0); + addArg(0,"remove","APT::Get::Remove",0); + addArg(0,"only-source","APT::Get::Only-Source",0); + addArg(0,"arch-only","APT::Get::Arch-Only",0); + addArg(0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0); + addArg(0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean); + addArg(0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean); + addArg(0,"fix-policy","APT::Get::Fix-Policy-Broken",0); + + return true; +} + /*}}}*/ +bool addArgumentsAPTMark(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/ +{ + if (CmdMatches("auto", "manual", "hold", "unhold", "showauto", + "showmanual", "showhold", "showholds", "install", + "markauto", "unmarkauto")) + ; + else + return false; + + addArg('v',"verbose","APT::MarkAuto::Verbose",0); + addArg('s',"simulate","APT::Mark::Simulate",0); + addArg('s',"just-print","APT::Mark::Simulate",0); + addArg('s',"recon","APT::Mark::Simulate",0); + addArg('s',"dry-run","APT::Mark::Simulate",0); + addArg('s',"no-act","APT::Mark::Simulate",0); + addArg('f',"file","Dir::State::extended_states",CommandLine::HasArg); + + return true; +} + /*}}}*/ +bool addArgumentsAPT(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/ +{ + if (CmdMatches("list")) + { + addArg(0,"installed","APT::Cmd::Installed",0); + addArg(0,"upgradable","APT::Cmd::Upgradable",0); + addArg('a', "all-versions", "APT::Cmd::AllVersions", 0); + } + else if (addArgumentsAPTGet(Args, Cmd) || addArgumentsAPTCache(Args, Cmd)) + { + // we have no (supported) command-name overlaps so far, so we call + // specifics in order until we find one which adds arguments + } + else + return false; + + return true; +} + /*}}}*/ +std::vector<CommandLine::Args> getCommandArgs(char const * const Program, char const * const Cmd)/*{{{*/ +{ + std::vector<CommandLine::Args> Args; + Args.reserve(50); + if (Program == NULL || Cmd == NULL) + ; // FIXME: Invalid command supplied + else if (strcmp(Cmd, "help") == 0) + ; // no options for help so no need to implement it in each + else if (strcmp(Program, "apt-get") == 0) + addArgumentsAPTGet(Args, Cmd); + else if (strcmp(Program, "apt-cache") == 0) + addArgumentsAPTCache(Args, Cmd); + else if (strcmp(Program, "apt-cdrom") == 0) + addArgumentsAPTCDROM(Args, Cmd); + else if (strcmp(Program, "apt-config") == 0) + addArgumentsAPTConfig(Args, Cmd); + else if (strcmp(Program, "apt-mark") == 0) + addArgumentsAPTMark(Args, Cmd); + else if (strcmp(Program, "apt") == 0) + addArgumentsAPT(Args, Cmd); + + // options without a command + addArg('h', "help", "help", 0); + addArg('v', "version", "version", 0); + // general options + addArg('q', "quiet", "quiet", CommandLine::IntLevel); + addArg('q', "silent", "quiet", CommandLine::IntLevel); + addArg('c', "config-file", 0, CommandLine::ConfigFile); + addArg('o', "option", 0, CommandLine::ArbItem); + addArg(0, NULL, NULL, 0); + + return Args; +} + /*}}}*/ +#undef CmdMatches +#undef addArg diff --git a/apt-private/private-cmndline.h b/apt-private/private-cmndline.h new file mode 100644 index 000000000..76045ffe7 --- /dev/null +++ b/apt-private/private-cmndline.h @@ -0,0 +1,10 @@ +#ifndef APT_PRIVATE_CMNDLINE_H +#define APT_PRIVATE_CMNDLINE_H + +#include <apt-pkg/cmndline.h> + +#include <vector> + +std::vector<CommandLine::Args> getCommandArgs(char const * const Program, char const * const Cmd); + +#endif diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc new file mode 100644 index 000000000..d5052fcc0 --- /dev/null +++ b/apt-private/private-install.cc @@ -0,0 +1,852 @@ +// Include Files /*{{{*/ +#include <config.h> + +#include <apt-pkg/aptconfiguration.h> +#include <apt-pkg/error.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/init.h> +#include <apt-pkg/depcache.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/algorithms.h> +#include <apt-pkg/acquire-item.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/clean.h> +#include <apt-pkg/srcrecords.h> +#include <apt-pkg/version.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/cacheset.h> +#include <apt-pkg/sptr.h> +#include <apt-pkg/md5.h> +#include <apt-pkg/versionmatch.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/pkgsystem.h> +#include <apt-pkg/pkgrecords.h> +#include <apt-pkg/indexfile.h> + +#include <set> +#include <locale.h> +#include <langinfo.h> +#include <fstream> +#include <termios.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/statfs.h> +#include <sys/statvfs.h> +#include <signal.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <regex.h> +#include <sys/wait.h> +#include <sstream> + +#include "private-install.h" +#include "private-cachefile.h" +#include "private-output.h" +#include "private-cacheset.h" +#include "acqprogress.h" + +#include <apti18n.h> + /*}}}*/ + +// CheckAuth - check if each download comes form a trusted source /*{{{*/ +// --------------------------------------------------------------------- +/* */ +static bool CheckAuth(pkgAcquire& Fetcher) +{ + std::string UntrustedList; + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I) + { + if (!(*I)->IsTrusted()) + { + UntrustedList += std::string((*I)->ShortDesc()) + " "; + } + } + + if (UntrustedList == "") + { + return true; + } + + ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,""); + + if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true) + { + c2out << _("Authentication warning overridden.\n"); + return true; + } + + if (_config->FindI("quiet",0) < 2 + && _config->FindB("APT::Get::Assume-Yes",false) == false) + { + c2out << _("Install these packages without verification?") << std::flush; + if (!YnPrompt(false)) + return _error->Error(_("Some packages could not be authenticated")); + + return true; + } + else if (_config->FindB("APT::Get::Force-Yes",false) == true) + { + return true; + } + + return _error->Error(_("There are problems and -y was used without --force-yes")); +} + /*}}}*/ + + +// InstallPackages - Actually download and install the packages /*{{{*/ +// --------------------------------------------------------------------- +/* This displays the informative messages describing what is going to + happen and then calls the download routines */ +bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) +{ + if (_config->FindB("APT::Get::Purge",false) == true) + { + pkgCache::PkgIterator I = Cache->PkgBegin(); + for (; I.end() == false; ++I) + { + if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete) + Cache->MarkDelete(I,true); + } + } + + bool Fail = false; + bool Essential = false; + + // Show all the various warning indicators + ShowDel(c1out,Cache); + ShowNew(c1out,Cache); + if (ShwKept == true) + ShowKept(c1out,Cache); + Fail |= !ShowHold(c1out,Cache); + if (_config->FindB("APT::Get::Show-Upgraded",true) == true) + ShowUpgraded(c1out,Cache); + Fail |= !ShowDowngraded(c1out,Cache); + if (_config->FindB("APT::Get::Download-Only",false) == false) + Essential = !ShowEssential(c1out,Cache); + Fail |= Essential; + Stats(c1out,Cache); + + // Sanity check + if (Cache->BrokenCount() != 0) + { + ShowBroken(c1out,Cache,false); + return _error->Error(_("Internal error, InstallPackages was called with broken packages!")); + } + + if (Cache->DelCount() == 0 && Cache->InstCount() == 0 && + Cache->BadCount() == 0) + return true; + + // No remove flag + if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false) + return _error->Error(_("Packages need to be removed but remove is disabled.")); + + // Run the simulator .. + if (_config->FindB("APT::Get::Simulate") == true) + { + pkgSimulate PM(Cache); + int status_fd = _config->FindI("APT::Status-Fd",-1); + pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd); + if (Res == pkgPackageManager::Failed) + return false; + if (Res != pkgPackageManager::Completed) + return _error->Error(_("Internal error, Ordering didn't finish")); + return true; + } + + // Create the text record parser + pkgRecords Recs(Cache); + if (_error->PendingError() == true) + return false; + + // Create the download object + pkgAcquire Fetcher; + AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); + if (_config->FindB("APT::Get::Print-URIs", false) == true) + { + // force a hashsum for compatibility reasons + _config->CndSet("Acquire::ForceHash", "md5sum"); + } + else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false) + return false; + + // Read the source list + if (Cache.BuildSourceList() == false) + return false; + pkgSourceList *List = Cache.GetSourceList(); + + // Create the package manager and prepare to download + SPtr<pkgPackageManager> PM= _system->CreatePM(Cache); + if (PM->GetArchives(&Fetcher,List,&Recs) == false || + _error->PendingError() == true) + return false; + + // Display statistics + unsigned long long FetchBytes = Fetcher.FetchNeeded(); + unsigned long long FetchPBytes = Fetcher.PartialPresent(); + unsigned long long DebBytes = Fetcher.TotalNeeded(); + if (DebBytes != Cache->DebSize()) + { + c0out << DebBytes << ',' << Cache->DebSize() << std::endl; + c0out << _("How odd.. The sizes didn't match, email apt@packages.debian.org") << std::endl; + } + + // Number of bytes + if (DebBytes != FetchBytes) + //TRANSLATOR: The required space between number and unit is already included + // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB + ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"), + SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str()); + else if (DebBytes != 0) + //TRANSLATOR: The required space between number and unit is already included + // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB + ioprintf(c1out,_("Need to get %sB of archives.\n"), + SizeToStr(DebBytes).c_str()); + + // Size delta + if (Cache->UsrSize() >= 0) + //TRANSLATOR: The required space between number and unit is already included + // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB + ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"), + SizeToStr(Cache->UsrSize()).c_str()); + else + //TRANSLATOR: The required space between number and unit is already included + // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB + ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"), + SizeToStr(-1*Cache->UsrSize()).c_str()); + + if (_error->PendingError() == true) + return false; + + /* Check for enough free space, but only if we are actually going to + download */ + if (_config->FindB("APT::Get::Print-URIs") == false && + _config->FindB("APT::Get::Download",true) == true) + { + struct statvfs Buf; + std::string OutputDir = _config->FindDir("Dir::Cache::Archives"); + if (statvfs(OutputDir.c_str(),&Buf) != 0) { + if (errno == EOVERFLOW) + return _error->WarningE("statvfs",_("Couldn't determine free space in %s"), + OutputDir.c_str()); + else + return _error->Errno("statvfs",_("Couldn't determine free space in %s"), + OutputDir.c_str()); + } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize) + { + struct statfs Stat; + if (statfs(OutputDir.c_str(),&Stat) != 0 +#if HAVE_STRUCT_STATFS_F_TYPE + || unsigned(Stat.f_type) != RAMFS_MAGIC +#endif + ) + return _error->Error(_("You don't have enough free space in %s."), + OutputDir.c_str()); + } + } + + // Fail safe check + if (_config->FindI("quiet",0) >= 2 || + _config->FindB("APT::Get::Assume-Yes",false) == true) + { + if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) + return _error->Error(_("There are problems and -y was used without --force-yes")); + } + + if (Essential == true && Safety == true) + { + if (_config->FindB("APT::Get::Trivial-Only",false) == true) + return _error->Error(_("Trivial Only specified but this is not a trivial operation.")); + + // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be + // careful with hard to type or special characters (like non-breaking spaces) + const char *Prompt = _("Yes, do as I say!"); + ioprintf(c2out, + _("You are about to do something potentially harmful.\n" + "To continue type in the phrase '%s'\n" + " ?] "),Prompt); + c2out << std::flush; + if (AnalPrompt(Prompt) == false) + { + c2out << _("Abort.") << std::endl; + exit(1); + } + } + else + { + // Prompt to continue + if (Ask == true || Fail == true) + { + if (_config->FindB("APT::Get::Trivial-Only",false) == true) + return _error->Error(_("Trivial Only specified but this is not a trivial operation.")); + + if (_config->FindI("quiet",0) < 2 && + _config->FindB("APT::Get::Assume-Yes",false) == false) + { + c2out << _("Do you want to continue?") << std::flush; + if (YnPrompt() == false) + { + c2out << _("Abort.") << std::endl; + exit(1); + } + } + } + } + + // Just print out the uris an exit if the --print-uris flag was used + if (_config->FindB("APT::Get::Print-URIs") == true) + { + pkgAcquire::UriIterator I = Fetcher.UriBegin(); + for (; I != Fetcher.UriEnd(); ++I) + c1out << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << + I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl; + return true; + } + + if (!CheckAuth(Fetcher)) + return false; + + /* Unlock the dpkg lock if we are not going to be doing an install + after. */ + if (_config->FindB("APT::Get::Download-Only",false) == true) + _system->UnLock(); + + // Run it + while (1) + { + bool Transient = false; + if (_config->FindB("APT::Get::Download",true) == false) + { + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();) + { + if ((*I)->Local == true) + { + ++I; + continue; + } + + // Close the item and check if it was found in cache + (*I)->Finished(); + if ((*I)->Complete == false) + Transient = true; + + // Clear it out of the fetch list + delete *I; + I = Fetcher.ItemsBegin(); + } + } + + if (Fetcher.Run() == pkgAcquire::Failed) + return false; + + // Print out errors + bool Failed = false; + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) + { + if ((*I)->Status == pkgAcquire::Item::StatDone && + (*I)->Complete == true) + continue; + + if ((*I)->Status == pkgAcquire::Item::StatIdle) + { + Transient = true; + // Failed = true; + continue; + } + + fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(), + (*I)->ErrorText.c_str()); + Failed = true; + } + + /* If we are in no download mode and missing files and there were + 'failures' then the user must specify -m. Furthermore, there + is no such thing as a transient error in no-download mode! */ + if (Transient == true && + _config->FindB("APT::Get::Download",true) == false) + { + Transient = false; + Failed = true; + } + + if (_config->FindB("APT::Get::Download-Only",false) == true) + { + if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false) + return _error->Error(_("Some files failed to download")); + c1out << _("Download complete and in download only mode") << std::endl; + return true; + } + + if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false) + { + return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?")); + } + + if (Transient == true && Failed == true) + return _error->Error(_("--fix-missing and media swapping is not currently supported")); + + // Try to deal with missing package files + if (Failed == true && PM->FixMissing() == false) + { + c2out << _("Unable to correct missing packages.") << std::endl; + return _error->Error(_("Aborting install.")); + } + + _system->UnLock(); + int status_fd = _config->FindI("APT::Status-Fd",-1); + pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd); + if (Res == pkgPackageManager::Failed || _error->PendingError() == true) + return false; + if (Res == pkgPackageManager::Completed) + break; + + // Reload the fetcher object and loop again for media swapping + Fetcher.Shutdown(); + if (PM->GetArchives(&Fetcher,List,&Recs) == false) + return false; + + _system->Lock(); + } + + std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages(); + if (disappearedPkgs.empty() == true) + return true; + + std::string disappear; + for (std::set<std::string>::const_iterator d = disappearedPkgs.begin(); + d != disappearedPkgs.end(); ++d) + disappear.append(*d).append(" "); + + ShowList(c1out, P_("The following package disappeared from your system as\n" + "all files have been overwritten by other packages:", + "The following packages disappeared from your system as\n" + "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, ""); + c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl; + + return true; +} + /*}}}*/ + + +// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/ +// --------------------------------------------------------------------- +/* Remove unused automatic packages */ +bool DoAutomaticRemove(CacheFile &Cache) +{ + bool Debug = _config->FindI("Debug::pkgAutoRemove",false); + bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false); + bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove"); + + pkgDepCache::ActionGroup group(*Cache); + if(Debug) + std::cout << "DoAutomaticRemove()" << std::endl; + + if (doAutoRemove == true && + _config->FindB("APT::Get::Remove",true) == false) + { + c1out << _("We are not supposed to delete stuff, can't start " + "AutoRemover") << std::endl; + return false; + } + + bool purgePkgs = _config->FindB("APT::Get::Purge", false); + bool smallList = (hideAutoRemove == false && + strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0); + + unsigned long autoRemoveCount = 0; + APT::PackageSet tooMuch; + APT::PackageList autoRemoveList; + // look over the cache to see what can be removed + for (unsigned J = 0; J < Cache->Head().PackageCount; ++J) + { + pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); + if (Cache[Pkg].Garbage) + { + if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install()) + if(Debug) + std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl; + + if (doAutoRemove) + { + if(Pkg.CurrentVer() != 0 && + Pkg->CurrentState != pkgCache::State::ConfigFiles) + Cache->MarkDelete(Pkg, purgePkgs, 0, false); + else + Cache->MarkKeep(Pkg, false, false); + } + else + { + if (hideAutoRemove == false && Cache[Pkg].Delete() == false) + autoRemoveList.insert(Pkg); + // if the package is a new install and already garbage we don't need to + // install it in the first place, so nuke it instead of show it + if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0) + { + if (Pkg.CandVersion() != 0) + tooMuch.insert(Pkg); + Cache->MarkDelete(Pkg, false, 0, false); + } + // only show stuff in the list that is not yet marked for removal + else if(hideAutoRemove == false && Cache[Pkg].Delete() == false) + ++autoRemoveCount; + } + } + } + + // we could have removed a new dependency of a garbage package, + // so check if a reverse depends is broken and if so install it again. + if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0)) + { + bool Changed; + do { + Changed = false; + for (APT::PackageSet::const_iterator Pkg = tooMuch.begin(); + Pkg != tooMuch.end() && Changed == false; ++Pkg) + { + APT::PackageSet too; + too.insert(*Pkg); + for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList(); + Prv.end() == false; ++Prv) + too.insert(Prv.ParentPkg()); + for (APT::PackageSet::const_iterator P = too.begin(); + P != too.end() && Changed == false; ++P) { + for (pkgCache::DepIterator R = P.RevDependsList(); + R.end() == false; ++R) + { + if (R.IsNegative() == true || + Cache->IsImportantDep(R) == false) + continue; + pkgCache::PkgIterator N = R.ParentPkg(); + if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false)) + continue; + if (Debug == true) + std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl; + Cache->MarkInstall(Pkg, false, 0, false); + if (hideAutoRemove == false) + ++autoRemoveCount; + tooMuch.erase(Pkg); + Changed = true; + break; + } + } + } + } while (Changed == true); + } + + std::string autoremovelist, autoremoveversions; + if (smallList == false && autoRemoveCount != 0) + { + for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg) + { + if (Cache[Pkg].Garbage == false) + continue; + autoremovelist += Pkg.FullName(true) + " "; + autoremoveversions += std::string(Cache[Pkg].CandVersion) + "\n"; + } + } + + // Now see if we had destroyed anything (if we had done anything) + if (Cache->BrokenCount() != 0) + { + c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n" + "shouldn't happen. Please file a bug report against apt.") << std::endl; + c1out << std::endl; + c1out << _("The following information may help to resolve the situation:") << std::endl; + c1out << std::endl; + ShowBroken(c1out,Cache,false); + + return _error->Error(_("Internal Error, AutoRemover broke stuff")); + } + + // if we don't remove them, we should show them! + if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0)) + { + if (smallList == false) + ShowList(c1out, P_("The following package was automatically installed and is no longer required:", + "The following packages were automatically installed and are no longer required:", + autoRemoveCount), autoremovelist, autoremoveversions); + else + ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n", + "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount); + c1out << P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount) << std::endl; + } + return true; +} + /*}}}*/ + + + + +// DoInstall - Install packages from the command line /*{{{*/ +// --------------------------------------------------------------------- +/* Install named packages */ +bool DoInstall(CommandLine &CmdL) +{ + CacheFile Cache; + if (Cache.OpenForInstall() == false || + Cache.CheckDeps(CmdL.FileSize() != 1) == false) + return false; + + // Enter the special broken fixing mode if the user specified arguments + bool BrokenFix = false; + if (Cache->BrokenCount() != 0) + BrokenFix = true; + + pkgProblemResolver* Fix = NULL; + if (_config->FindB("APT::Get::CallResolver", true) == true) + Fix = new pkgProblemResolver(Cache); + + static const unsigned short MOD_REMOVE = 1; + static const unsigned short MOD_INSTALL = 2; + + unsigned short fallback = MOD_INSTALL; + if (strcasecmp(CmdL.FileList[0],"remove") == 0) + fallback = MOD_REMOVE; + else if (strcasecmp(CmdL.FileList[0], "purge") == 0) + { + _config->Set("APT::Get::Purge", true); + fallback = MOD_REMOVE; + } + else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0) + { + _config->Set("APT::Get::AutomaticRemove", "true"); + fallback = MOD_REMOVE; + } + + std::list<APT::VersionSet::Modifier> mods; + mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+", + APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE)); + mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-", + APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST)); + CacheSetHelperAPTGet helper(c0out); + std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache, + CmdL.FileList + 1, mods, fallback, helper); + + if (_error->PendingError() == true) + { + helper.showVirtualPackageErrors(Cache); + if (Fix != NULL) + delete Fix; + return false; + } + + + TryToInstall InstallAction(Cache, Fix, BrokenFix); + TryToRemove RemoveAction(Cache, Fix); + + // new scope for the ActionGroup + { + pkgDepCache::ActionGroup group(Cache); + unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 }; + + for (unsigned short i = 0; order[i] != 0; ++i) + { + if (order[i] == MOD_INSTALL) + InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction); + else if (order[i] == MOD_REMOVE) + RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction); + } + + if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true) + { + for (unsigned short i = 0; order[i] != 0; ++i) + { + if (order[i] != MOD_INSTALL) + continue; + InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out); + InstallAction.doAutoInstall(); + } + } + + if (_error->PendingError() == true) + { + if (Fix != NULL) + delete Fix; + return false; + } + + /* If we are in the Broken fixing mode we do not attempt to fix the + problems. This is if the user invoked install without -f and gave + packages */ + if (BrokenFix == true && Cache->BrokenCount() != 0) + { + c1out << _("You might want to run 'apt-get -f install' to correct these:") << std::endl; + ShowBroken(c1out,Cache,false); + if (Fix != NULL) + delete Fix; + return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).")); + } + + if (Fix != NULL) + { + // Call the scored problem resolver + Fix->Resolve(true); + delete Fix; + } + + // Now we check the state of the packages, + if (Cache->BrokenCount() != 0) + { + c1out << + _("Some packages could not be installed. This may mean that you have\n" + "requested an impossible situation or if you are using the unstable\n" + "distribution that some required packages have not yet been created\n" + "or been moved out of Incoming.") << std::endl; + /* + if (Packages == 1) + { + c1out << std::endl; + c1out << + _("Since you only requested a single operation it is extremely likely that\n" + "the package is simply not installable and a bug report against\n" + "that package should be filed.") << std::endl; + } + */ + + c1out << _("The following information may help to resolve the situation:") << std::endl; + c1out << std::endl; + ShowBroken(c1out,Cache,false); + if (_error->PendingError() == true) + return false; + else + return _error->Error(_("Broken packages")); + } + } + if (!DoAutomaticRemove(Cache)) + return false; + + /* Print out a list of packages that are going to be installed extra + to what the user asked */ + if (Cache->InstCount() != verset[MOD_INSTALL].size()) + { + std::string List; + std::string VersionsList; + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator I(Cache,Cache.List[J]); + if ((*Cache)[I].Install() == false) + continue; + pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache); + + if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end()) + continue; + + List += I.FullName(true) + " "; + VersionsList += std::string(Cache[I].CandVersion) + "\n"; + } + + ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList); + } + + /* Print out a list of suggested and recommended packages */ + { + std::string SuggestsList, RecommendsList; + std::string SuggestsVersions, RecommendsVersions; + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); + + /* Just look at the ones we want to install */ + if ((*Cache)[Pkg].Install() == false) + continue; + + // get the recommends/suggests for the candidate ver + pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache); + for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; ) + { + pkgCache::DepIterator Start; + pkgCache::DepIterator End; + D.GlobOr(Start,End); // advances D + + // FIXME: we really should display a or-group as a or-group to the user + // the problem is that ShowList is incapable of doing this + std::string RecommendsOrList,RecommendsOrVersions; + std::string SuggestsOrList,SuggestsOrVersions; + bool foundInstalledInOrGroup = false; + for(;;) + { + /* Skip if package is installed already, or is about to be */ + std::string target = Start.TargetPkg().FullName(true) + " "; + pkgCache::PkgIterator const TarPkg = Start.TargetPkg(); + if (TarPkg->SelectedState == pkgCache::State::Install || + TarPkg->SelectedState == pkgCache::State::Hold || + Cache[Start.TargetPkg()].Install()) + { + foundInstalledInOrGroup=true; + break; + } + + /* Skip if we already saw it */ + if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1) + { + foundInstalledInOrGroup=true; + break; + } + + // this is a dep on a virtual pkg, check if any package that provides it + // should be installed + if(Start.TargetPkg().ProvidesList() != 0) + { + pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList(); + for (; I.end() == false; ++I) + { + pkgCache::PkgIterator Pkg = I.OwnerPkg(); + if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() && + Pkg.CurrentVer() != 0) + foundInstalledInOrGroup=true; + } + } + + if (Start->Type == pkgCache::Dep::Suggests) + { + SuggestsOrList += target; + SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n"; + } + + if (Start->Type == pkgCache::Dep::Recommends) + { + RecommendsOrList += target; + RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n"; + } + + if (Start >= End) + break; + ++Start; + } + + if(foundInstalledInOrGroup == false) + { + RecommendsList += RecommendsOrList; + RecommendsVersions += RecommendsOrVersions; + SuggestsList += SuggestsOrList; + SuggestsVersions += SuggestsOrVersions; + } + + } + } + + ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions); + ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions); + + } + + // if nothing changed in the cache, but only the automark information + // we write the StateFile here, otherwise it will be written in + // cache.commit() + if (InstallAction.AutoMarkChanged > 0 && + Cache->DelCount() == 0 && Cache->InstCount() == 0 && + Cache->BadCount() == 0 && + _config->FindB("APT::Get::Simulate",false) == false) + Cache->writeStateFile(NULL); + + // See if we need to prompt + // FIXME: check if really the packages in the set are going to be installed + if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0) + return InstallPackages(Cache,false,false); + + return InstallPackages(Cache,false); +} + /*}}}*/ diff --git a/apt-private/private-install.h b/apt-private/private-install.h new file mode 100644 index 000000000..fcf4cbced --- /dev/null +++ b/apt-private/private-install.h @@ -0,0 +1,181 @@ +#ifndef APT_PRIVATE_INSTALL_H +#define APT_PRIVATE_INSTALL_H + +#include <apt-pkg/cacheset.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/strutl.h> + +#include "private-cachefile.h" +#include "private-output.h" + +#include <apti18n.h> + +#define RAMFS_MAGIC 0x858458f6 + +bool DoInstall(CommandLine &Cmd); + + +bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, + bool Safety = true); + + +// TryToInstall - Mark a package for installation /*{{{*/ +struct TryToInstall { + pkgCacheFile* Cache; + pkgProblemResolver* Fix; + bool FixBroken; + unsigned long AutoMarkChanged; + APT::PackageSet doAutoInstallLater; + + TryToInstall(pkgCacheFile &Cache, pkgProblemResolver *PM, bool const FixBroken) : Cache(&Cache), Fix(PM), + FixBroken(FixBroken), AutoMarkChanged(0) {}; + + void operator() (pkgCache::VerIterator const &Ver) { + pkgCache::PkgIterator Pkg = Ver.ParentPkg(); + + Cache->GetDepCache()->SetCandidateVersion(Ver); + pkgDepCache::StateCache &State = (*Cache)[Pkg]; + + // Handle the no-upgrade case + if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0) + ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"), + Pkg.FullName(true).c_str()); + // Ignore request for install if package would be new + else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0) + ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"), + Pkg.FullName(true).c_str()); + else { + if (Fix != NULL) { + Fix->Clear(Pkg); + Fix->Protect(Pkg); + } + Cache->GetDepCache()->MarkInstall(Pkg,false); + + if (State.Install() == false) { + if (_config->FindB("APT::Get::ReInstall",false) == true) { + if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false) + ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"), + Pkg.FullName(true).c_str()); + else + Cache->GetDepCache()->SetReInstall(Pkg, true); + } else + ioprintf(c1out,_("%s is already the newest version.\n"), + Pkg.FullName(true).c_str()); + } + + // Install it with autoinstalling enabled (if we not respect the minial + // required deps or the policy) + if (FixBroken == false) + doAutoInstallLater.insert(Pkg); + } + + // see if we need to fix the auto-mark flag + // e.g. apt-get install foo + // where foo is marked automatic + if (State.Install() == false && + (State.Flags & pkgCache::Flag::Auto) && + _config->FindB("APT::Get::ReInstall",false) == false && + _config->FindB("APT::Get::Only-Upgrade",false) == false && + _config->FindB("APT::Get::Download-Only",false) == false) + { + ioprintf(c1out,_("%s set to manually installed.\n"), + Pkg.FullName(true).c_str()); + Cache->GetDepCache()->MarkAuto(Pkg,false); + AutoMarkChanged++; + } + } + + bool propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > start, std::ostream &out) + { + for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin(); + s != start.end(); ++s) + Cache->GetDepCache()->SetCandidateVersion(s->first); + + bool Success = true; + std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed; + for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin(); + s != start.end(); ++s) + { + Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache))); + // We continue here even if it failed to enhance the ShowBroken output + Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed); + } + for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin(); + c != Changed.end(); ++c) + { + if (c->second.end() == true) + ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"), + c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str()); + else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group) + { + pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache); + ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(), + V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str()); + } + } + return Success; + } + + void doAutoInstall() { + for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin(); + P != doAutoInstallLater.end(); ++P) { + pkgDepCache::StateCache &State = (*Cache)[P]; + if (State.InstBroken() == false && State.InstPolicyBroken() == false) + continue; + Cache->GetDepCache()->MarkInstall(P, true); + } + doAutoInstallLater.clear(); + } +}; + /*}}}*/ +// TryToRemove - Mark a package for removal /*{{{*/ +struct TryToRemove { + pkgCacheFile* Cache; + pkgProblemResolver* Fix; + bool PurgePkgs; + + TryToRemove(pkgCacheFile &Cache, pkgProblemResolver *PM) : Cache(&Cache), Fix(PM), + PurgePkgs(_config->FindB("APT::Get::Purge", false)) {}; + + void operator() (pkgCache::VerIterator const &Ver) + { + pkgCache::PkgIterator Pkg = Ver.ParentPkg(); + + if (Fix != NULL) + { + Fix->Clear(Pkg); + Fix->Protect(Pkg); + Fix->Remove(Pkg); + } + + if ((Pkg->CurrentVer == 0 && PurgePkgs == false) || + (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled)) + { + pkgCache::GrpIterator Grp = Pkg.Group(); + pkgCache::PkgIterator P = Grp.PackageList(); + for (; P.end() != true; P = Grp.NextPkg(P)) + { + if (P == Pkg) + continue; + if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled)) + { + // TRANSLATORS: Note, this is not an interactive question + ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"), + Pkg.FullName(true).c_str(), P.FullName(true).c_str()); + break; + } + } + if (P.end() == true) + ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str()); + + // MarkInstall refuses to install packages on hold + Pkg->SelectedState = pkgCache::State::Hold; + } + else + Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs); + } +}; + /*}}}*/ + + +#endif diff --git a/apt-private/private-list.cc b/apt-private/private-list.cc new file mode 100644 index 000000000..ac72ce51a --- /dev/null +++ b/apt-private/private-list.cc @@ -0,0 +1,158 @@ +// Include Files /*{{{*/ +#include <config.h> + +#include <apt-pkg/error.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/cachefilter.h> +#include <apt-pkg/cacheset.h> +#include <apt-pkg/init.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/pkgrecords.h> +#include <apt-pkg/srcrecords.h> +#include <apt-pkg/version.h> +#include <apt-pkg/policy.h> +#include <apt-pkg/tagfile.h> +#include <apt-pkg/algorithms.h> +#include <apt-pkg/sptr.h> +#include <apt-pkg/pkgsystem.h> +#include <apt-pkg/indexfile.h> +#include <apt-pkg/metaindex.h> + +#include <sstream> +#include <vector> +#include <utility> +#include <cassert> +#include <locale.h> +#include <iostream> +#include <unistd.h> +#include <errno.h> +#include <regex.h> +#include <stdio.h> +#include <algorithm> + +#include "private-cmndline.h" +#include "private-list.h" +#include "private-output.h" +#include "private-cacheset.h" + +#include <apti18n.h> + /*}}}*/ + +struct PackageSortAlphabetic +{ + bool operator () (const pkgCache::PkgIterator &p_lhs, + const pkgCache::PkgIterator &p_rhs) + { + const std::string &l_name = p_lhs.FullName(true); + const std::string &r_name = p_rhs.FullName(true); + return (l_name < r_name); + } +}; + +class PackageNameMatcher : public Matcher +{ + public: + PackageNameMatcher(const char **patterns) + { + for(int i=0; patterns[i] != NULL; i++) + { + std::string pattern = patterns[i]; + APT::CacheFilter::PackageMatcher *cachefilter = NULL; + if(_config->FindB("APT::Cmd::UseRegexp", false) == true) + cachefilter = new APT::CacheFilter::PackageNameMatchesRegEx(pattern); + else + cachefilter = new APT::CacheFilter::PackageNameMatchesFnmatch(pattern); + filters.push_back(cachefilter); + } + } + virtual ~PackageNameMatcher() + { + for(J=filters.begin(); J != filters.end(); J++) + delete *J; + } + virtual bool operator () (const pkgCache::PkgIterator &P) + { + for(J=filters.begin(); J != filters.end(); J++) + { + APT::CacheFilter::PackageMatcher *cachefilter = *J; + if((*cachefilter)(P)) + return true; + } + return false; + } + +private: + std::vector<APT::CacheFilter::PackageMatcher*> filters; + std::vector<APT::CacheFilter::PackageMatcher*>::const_iterator J; +}; + + +void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records, + pkgCache::PkgIterator P, + std::ostream &outs) +{ + for (pkgCache::VerIterator Ver = P.VersionList(); + Ver.end() == false; Ver++) + ListSingleVersion(CacheFile, records, Ver, outs); +} + +// list - list package based on criteria /*{{{*/ +// --------------------------------------------------------------------- +bool List(CommandLine &Cmd) +{ + pkgCacheFile CacheFile; + pkgCache *Cache = CacheFile.GetPkgCache(); + pkgRecords records(CacheFile); + + if (unlikely(Cache == NULL)) + return false; + + const char **patterns; + const char *all_pattern[] = { "*", NULL}; + + if (strv_length(Cmd.FileList + 1) == 0) + { + patterns = all_pattern; + } else { + patterns = Cmd.FileList + 1; + } + + std::map<std::string, std::string> output_map; + std::map<std::string, std::string>::const_iterator K; + + PackageNameMatcher matcher(patterns); + LocalitySortedVersionSet bag; + OpTextProgress progress; + progress.OverallProgress(0, + Cache->Head().PackageCount, + Cache->Head().PackageCount, + _("Listing")); + GetLocalitySortedVersionSet(CacheFile, bag, matcher, progress); + for (LocalitySortedVersionSet::iterator V = bag.begin(); V != bag.end(); V++) + { + std::stringstream outs; + if(_config->FindB("APT::Cmd::AllVersions", false) == true) + { + ListAllVersions(CacheFile, records, V.ParentPkg(), outs); + output_map.insert(std::make_pair<std::string, std::string>( + V.ParentPkg().Name(), outs.str())); + } else { + ListSingleVersion(CacheFile, records, V, outs); + output_map.insert(std::make_pair<std::string, std::string>( + V.ParentPkg().Name(), outs.str())); + } + } + + // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status) + // output the sorted map + for (K = output_map.begin(); K != output_map.end(); K++) + std::cout << (*K).second << std::endl; + + + return true; +} + diff --git a/apt-private/private-list.h b/apt-private/private-list.h new file mode 100644 index 000000000..6f5aad27a --- /dev/null +++ b/apt-private/private-list.h @@ -0,0 +1,9 @@ +#ifndef APT_PRIVATE_LIST_H +#define APT_PRIVATE_LIST_H + +#include <apt-pkg/cmndline.h> + +bool List(CommandLine &Cmd); + + +#endif diff --git a/apt-private/private-main.cc b/apt-private/private-main.cc new file mode 100644 index 000000000..1fdf3f0be --- /dev/null +++ b/apt-private/private-main.cc @@ -0,0 +1,26 @@ + +#include<unistd.h> +#include<cstring> + +#include <apt-pkg/configuration.h> +#include "private-main.h" + +#include <apti18n.h> + +void CheckSimulateMode(CommandLine &CmdL) +{ + // simulate user-friendly if apt-get has no root privileges + if (getuid() != 0 && _config->FindB("APT::Get::Simulate") == true && + (CmdL.FileSize() == 0 || + (strcmp(CmdL.FileList[0], "source") != 0 && strcmp(CmdL.FileList[0], "download") != 0 && + strcmp(CmdL.FileList[0], "changelog") != 0))) + { + if (_config->FindB("APT::Get::Show-User-Simulation-Note",true) == true) + std::cout << _("NOTE: This is only a simulation!\n" + " apt-get needs root privileges for real execution.\n" + " Keep also in mind that locking is deactivated,\n" + " so don't depend on the relevance to the real current situation!" + ) << std::endl; + _config->Set("Debug::NoLocking",true); + } +} diff --git a/apt-private/private-main.h b/apt-private/private-main.h new file mode 100644 index 000000000..f9a95c4ec --- /dev/null +++ b/apt-private/private-main.h @@ -0,0 +1,9 @@ +#ifndef APT_PRIVATE_MAIN_H +#define APT_PRIVATE_MAIN_H + +#include <apt-pkg/cmndline.h> + +void CheckSimulateMode(CommandLine &CmdL); + + +#endif diff --git a/apt-private/private-moo.cc b/apt-private/private-moo.cc new file mode 100644 index 000000000..9b5b94654 --- /dev/null +++ b/apt-private/private-moo.cc @@ -0,0 +1,193 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Here be cows โ but: Never ask, never tell + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include<config.h> + +#include <apt-pkg/configuration.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/strutl.h> + +#include <strings.h> +#include <sstream> + +#include "private-moo.h" +#include "private-output.h" + +#include <apti18n.h> + /*}}}*/ + +std::string getMooLine() { /*{{{*/ + time_t const timenow = time(NULL); + struct tm special; + localtime_r(&timenow, &special); + enum { NORMAL, PACKAGEMANAGER, APPRECIATION, AGITATION, AIRBORN } line; + if (special.tm_mon == 11 && special.tm_mday == 25) + line = PACKAGEMANAGER; + else if (special.tm_mon == 7 && special.tm_mday == 16) + line = APPRECIATION; + else if (special.tm_mon == 10 && special.tm_mday == 7) + line = AGITATION; + else if (special.tm_mon == 1 && special.tm_mday == 18) + line = AIRBORN; + else + line = NORMAL; + + bool const quiet = _config->FindI("quiet") >= 2; + std::ostringstream out; + if (quiet == false) + out << "...\""; + + switch(line) + { + case PACKAGEMANAGER: out << "Happy package management day!"; break; + case APPRECIATION: out << "Three moos for Debian!"; break; + case AGITATION: out << "Whoever needs milk, bows to the animal."; break; + case AIRBORN: out << "It's a Bird ... It's a Plane ... It's Super Cow!"; break; + default: out << "Have you mooed today?"; break; + } + + if (quiet == true) + out << std::endl; + else + out << "\"..." << std::endl; + + return out.str(); +} + /*}}}*/ +bool printMooLine() { /*{{{*/ + std::cerr << getMooLine() << std::endl; + return true; +} + /*}}}*/ +bool DoMoo1(CommandLine &CmdL) /*{{{*/ +{ + // our trustworthy super cow since 2001 + if (_config->FindI("quiet") >= 2) + return printMooLine(); + std::string const moo = getMooLine(); + size_t const depth = moo.length()/4; + c1out << + OutputInDepth(depth, " ") << " (__) \n" << + OutputInDepth(depth, " ") << " (oo) \n" << + OutputInDepth(depth, " ") << " /------\\/ \n" << + OutputInDepth(depth, " ") << " / | || \n" << + OutputInDepth(depth, " ") << " * /\\---/\\ \n" << + OutputInDepth(depth, " ") << " ~~ ~~ \n" << + moo; + return true; +} + /*}}}*/ +bool DoMoo2(CommandLine &CmdL) /*{{{*/ +{ + // by Fernando Ribeiro in lp:56125 + if (_config->FindI("quiet") >= 2) + return printMooLine(); + std::string const moo = getMooLine(); + size_t const depth = moo.length()/4; + if (_config->FindB("APT::Moo::Color", false) == false) + c1out << + OutputInDepth(depth, " ") << " (__) \n" << + OutputInDepth(depth, " ") << " _______~(..)~ \n" << + OutputInDepth(depth, " ") << " ,----\\(oo) \n" << + OutputInDepth(depth, " ") << " /|____|,' \n" << + OutputInDepth(depth, " ") << " * /\"\\ /\\ \n" << + OutputInDepth(depth, " ") << " ~ ~ ~ ~ \n" << + moo; + else + { + c1out << + OutputInDepth(depth, " ") << " \e[1;97m(\e[0;33m__\e[1;97m)\e[0m\n" << + OutputInDepth(depth, " ") << " \e[31m_______\e[33m~(\e[1;34m..\e[0;33m)~\e[0m\n" << + OutputInDepth(depth, " ") << " \e[33m,----\e[31m\\\e[33m(\e[1;4;35moo\e[0;33m)\e[0m\n" << + OutputInDepth(depth, " ") << " \e[33m/|____|,'\e[0m\n" << + OutputInDepth(depth, " ") << " \e[1;5;97m*\e[0;33m /\\ /\\\e[0m\n" << + "\e[32m"; + for (size_t i = moo.length()/2; i > 1; --i) + c1out << "wW"; + + c1out << "w\e[0m\n" << moo; + } + + return true; +} + /*}}}*/ +bool DoMoo3(CommandLine &CmdL) /*{{{*/ +{ + // by Robert Millan in deb:134156 + if (_config->FindI("quiet") >= 2) + return printMooLine(); + std::string const moo = getMooLine(); + size_t const depth = moo.length()/16; + c1out << + OutputInDepth(depth, " ") << " \\_/ \n" << + OutputInDepth(depth, " ") << " m00h (__) -(_)- \n" << + OutputInDepth(depth, " ") << " \\ ~Oo~___ / \\\n" << + OutputInDepth(depth, " ") << " (..) |\\ \n" << + OutputInDepth(depth, "_") << "_________|_|_|__________" << + OutputInDepth((moo.length() - (depth + 27)), "_") << "\n" << moo; + return true; +} + /*}}}*/ +bool DoMooApril(CommandLine &CmdL) /*{{{*/ +{ + // by Christopher Allan Webber and proposed by Paul Tagliamonte + // in a "Community outreach": https://lists.debian.org/debian-devel/2013/04/msg00045.html + if (_config->FindI("quiet") >= 2) + { + std::cerr << "Have you smashed some milk today?" << std::endl; + return true; + } + c1out << + " _ _\n" + " (_\\___( \\,\n" + " )___ _ Have you smashed some milk today?\n" + " /( (_)-(_) /\n" + " ,---------' \\_\n" + " //( ',__,' \\ (' ')\n" + " // ) '----'\n" + " '' ; \\ .--. ,/\n" + " | )',_,'----( ;\n" + " ||| ''' '||\n"; + return true; +} + /*}}}*/ +bool DoMoo(CommandLine &CmdL) /*{{{*/ +{ + time_t const timenow = time(NULL); + struct tm april; + localtime_r(&timenow, &april); + if (april.tm_mday == 1 && april.tm_mon == 3) + return DoMooApril(CmdL); + + signed short SuperCow = 1; + if (CmdL.FileSize() != 0) + for (const char **Moo = CmdL.FileList + 1; *Moo != 0; Moo++) + if (strcasecmp(*Moo, "moo") == 0) + SuperCow++; + + // time is random enough for our purpose + if (SuperCow > 3) + { + if (april.tm_sec == 1) + SuperCow = 1 + (timenow % 4); + else + SuperCow = 1 + (timenow % 3); + } + + switch(SuperCow) { + case 1: return DoMoo1(CmdL); + case 2: return DoMoo2(CmdL); + case 3: return DoMoo3(CmdL); + case 4: return DoMooApril(CmdL); + default: return DoMoo1(CmdL); + } + + return true; +} + /*}}}*/ diff --git a/apt-private/private-moo.h b/apt-private/private-moo.h new file mode 100644 index 000000000..7bfc5c1fc --- /dev/null +++ b/apt-private/private-moo.h @@ -0,0 +1,12 @@ +#ifndef APT_PRIVATE_MOO_H +#define APT_PRIVATE_MOO_H + +class CommandLine; + +bool DoMoo(CommandLine &CmdL); +bool DoMoo1(CommandLine &CmdL); +bool DoMoo2(CommandLine &CmdL); +bool DoMoo3(CommandLine &CmdL); +bool DoMooApril(CommandLine &CmdL); + +#endif diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc new file mode 100644 index 000000000..659975476 --- /dev/null +++ b/apt-private/private-output.cc @@ -0,0 +1,753 @@ +// Include files /*{{{*/ +#include<config.h> + +#include <apt-pkg/configuration.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/error.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/pkgrecords.h> +#include <apt-pkg/policy.h> + +#include <iomanip> +#include <iostream> +#include <locale.h> +#include <langinfo.h> +#include <unistd.h> + +#include "private-output.h" +#include "private-cachefile.h" + +#include <apti18n.h> + /*}}}*/ + +using namespace std; + +std::ostream c0out(0); +std::ostream c1out(0); +std::ostream c2out(0); +std::ofstream devnull("/dev/null"); +unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */ + + +bool InitOutput() +{ + c0out.rdbuf(cout.rdbuf()); + c1out.rdbuf(cout.rdbuf()); + c2out.rdbuf(cout.rdbuf()); + if (_config->FindI("quiet",0) > 0) + c0out.rdbuf(devnull.rdbuf()); + if (_config->FindI("quiet",0) > 1) + c1out.rdbuf(devnull.rdbuf()); + + if(!isatty(1)) + { + _config->Set("APT::Color", "false"); + _config->Set("APT::Color::Highlight", ""); + _config->Set("APT::Color::Neutral", ""); + } else { + // Colors + _config->CndSet("APT::Color::Highlight", "\x1B[32m"); + _config->CndSet("APT::Color::Neutral", "\x1B[0m"); + + _config->CndSet("APT::Color::Red", "\x1B[31m"); + _config->CndSet("APT::Color::Green", "\x1B[32m"); + _config->CndSet("APT::Color::Yellow", "\x1B[33m"); + _config->CndSet("APT::Color::Blue", "\x1B[34m"); + _config->CndSet("APT::Color::Magenta", "\x1B[35m"); + _config->CndSet("APT::Color::Cyan", "\x1B[36m"); + _config->CndSet("APT::Color::White", "\x1B[37m"); + } + + return true; +} + +std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver) +{ + std::string suite = ""; + if (ver && ver.FileList() && ver.FileList()) + { + pkgCache::VerFileIterator VF = ver.FileList(); + for (; VF.end() == false ; ++VF) + { + // XXX: how to figure out the relevant suite? if its in multiple ones? + suite = suite + "," + VF.File().Archive(); + //suite = VF.File().Archive(); + } + suite = suite.erase(0, 1); + } + return suite; +} + +std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) +{ + pkgDepCache *DepCache = CacheFile.GetDepCache(); + pkgDepCache::StateCache &state = (*DepCache)[P]; + + std::string flags_str; + if (state.NowBroken()) + flags_str = "B"; + if (P.CurrentVer() && state.Upgradable()) + flags_str = "g"; + else if (P.CurrentVer() != NULL) + flags_str = "i"; + else + flags_str = "-"; + return flags_str; +} + +std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) +{ + pkgPolicy *policy = CacheFile.GetPolicy(); + pkgCache::VerIterator cand = policy->GetCandidateVer(P); + + return cand ? cand.VerStr() : "(none)"; +} + +std::string GetInstalledVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) +{ + pkgCache::VerIterator inst = P.CurrentVer(); + + return inst ? inst.VerStr() : "(none)"; +} + +std::string GetVersion(pkgCacheFile &CacheFile, pkgCache::VerIterator V) +{ + pkgCache::PkgIterator P = V.ParentPkg(); + if (V == P.CurrentVer()) + { + pkgDepCache *DepCache = CacheFile.GetDepCache(); + pkgDepCache::StateCache &state = (*DepCache)[P]; + std::string inst_str = DeNull(V.VerStr()); + if (state.Upgradable()) + return "**"+inst_str; + return inst_str; + } + + if(V) + return DeNull(V.VerStr()); + return "(none)"; +} + +std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) +{ + pkgPolicy *policy = CacheFile.GetPolicy(); + pkgCache::VerIterator inst = P.CurrentVer(); + pkgCache::VerIterator cand = policy->GetCandidateVer(P); + + return inst ? inst.Arch() : cand.Arch(); +} + +std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P) +{ + pkgPolicy *policy = CacheFile.GetPolicy(); + + pkgCache::VerIterator ver; + if (P.CurrentVer()) + ver = P.CurrentVer(); + else + ver = policy->GetCandidateVer(P); + + std::string ShortDescription = "(none)"; + if(ver) + { + pkgCache::DescIterator Desc = ver.TranslatedDescription(); + pkgRecords::Parser & parser = records.Lookup(Desc.FileList()); + + ShortDescription = parser.ShortDesc(); + } + return ShortDescription; +} + +void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, + pkgCache::VerIterator V, std::ostream &out) +{ + pkgCache::PkgIterator P = V.ParentPkg(); + + pkgDepCache *DepCache = CacheFile.GetDepCache(); + pkgDepCache::StateCache &state = (*DepCache)[P]; + + std::string suite = GetArchiveSuite(CacheFile, V); + std::string name_str = P.Name(); + + if (_config->FindB("APT::Cmd::use-format", false)) + { + std::string format = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}"); + std::string output = format; + + output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P)); + output = SubstVar(output, "${Package}", name_str); + output = SubstVar(output, "${installed:Version}", GetInstalledVersion(CacheFile, P)); + output = SubstVar(output, "${candidate:Version}", GetCandidateVersion(CacheFile, P)); + output = SubstVar(output, "${Version}", GetVersion(CacheFile, V)); + output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P)); + output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V)); + out << output << std::endl; + } else { + // raring/linux-kernel version [upradable: new-version] + // description + pkgPolicy *policy = CacheFile.GetPolicy(); + out << std::setiosflags(std::ios::left) + << _config->Find("APT::Color::Highlight", "") + << name_str + << _config->Find("APT::Color::Neutral", "") + << "/" << suite + << " "; + if(P.CurrentVer() == V && state.Upgradable()) { + out << GetVersion(CacheFile, V) + << " " + << "[" << _("installed,upgradable to: ") + << GetCandidateVersion(CacheFile, P) << "]"; + } else if (P.CurrentVer() == V) { + out << GetVersion(CacheFile, V) + << " "; + if(!V.Downloadable()) + out << _("[installed,local]"); + else + if(V.Automatic() && state.Garbage) + out << _("[installed,auto-removable]"); + else if (state.Flags & pkgCache::Flag::Auto) + out << _("[installed,automatic]"); + else + out << _("[installed]"); + } else if (P.CurrentVer() && + policy->GetCandidateVer(P) == V && + state.Upgradable()) { + out << GetVersion(CacheFile, V) + << " " + << _("[upgradable from: ") + << GetInstalledVersion(CacheFile, P) << "]"; + } else { + if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles) + out << GetVersion(CacheFile, V) + << " " + << _("[residual-config]"); + else + out << GetVersion(CacheFile, V); + } + out << " " << GetArchitecture(CacheFile, P) << " "; + out << std::endl + << " " << GetShortDescription(CacheFile, records, P) + << std::endl; + } +} + + +// ShowList - Show a list /*{{{*/ +// --------------------------------------------------------------------- +/* This prints out a string of space separated words with a title and + a two space indent line wraped to the current screen width. */ +bool ShowList(ostream &out,string Title,string List,string VersionsList) +{ + if (List.empty() == true) + return true; + // trim trailing space + int NonSpace = List.find_last_not_of(' '); + if (NonSpace != -1) + { + List = List.erase(NonSpace + 1); + if (List.empty() == true) + return true; + } + + // Acount for the leading space + int ScreenWidth = ::ScreenWidth - 3; + + out << Title << endl; + string::size_type Start = 0; + string::size_type VersionsStart = 0; + while (Start < List.size()) + { + if(_config->FindB("APT::Get::Show-Versions",false) == true && + VersionsList.size() > 0) { + string::size_type End; + string::size_type VersionsEnd; + + End = List.find(' ',Start); + VersionsEnd = VersionsList.find('\n', VersionsStart); + + out << " " << string(List,Start,End - Start) << " (" << + string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) << + ")" << endl; + + if (End == string::npos || End < Start) + End = Start + ScreenWidth; + + Start = End + 1; + VersionsStart = VersionsEnd + 1; + } else { + string::size_type End; + + if (Start + ScreenWidth >= List.size()) + End = List.size(); + else + End = List.rfind(' ',Start+ScreenWidth); + + if (End == string::npos || End < Start) + End = Start + ScreenWidth; + out << " " << string(List,Start,End - Start) << endl; + Start = End + 1; + } + } + + return false; +} + /*}}}*/ +// ShowBroken - Debugging aide /*{{{*/ +// --------------------------------------------------------------------- +/* This prints out the names of all the packages that are broken along + with the name of each each broken dependency and a quite version + description. + + The output looks like: + The following packages have unmet dependencies: + exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed + Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed + Depends: libsasl7 but it is not going to be installed + */ +void ShowBroken(ostream &out,CacheFile &Cache,bool Now) +{ + if (Cache->BrokenCount() == 0) + return; + + out << _("The following packages have unmet dependencies:") << endl; + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator I(Cache,Cache.List[J]); + + if (Now == true) + { + if (Cache[I].NowBroken() == false) + continue; + } + else + { + if (Cache[I].InstBroken() == false) + continue; + } + + // Print out each package and the failed dependencies + out << " " << I.FullName(true) << " :"; + unsigned const Indent = I.FullName(true).size() + 3; + bool First = true; + pkgCache::VerIterator Ver; + + if (Now == true) + Ver = I.CurrentVer(); + else + Ver = Cache[I].InstVerIter(Cache); + + if (Ver.end() == true) + { + out << endl; + continue; + } + + for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) + { + // Compute a single dependency element (glob or) + pkgCache::DepIterator Start; + pkgCache::DepIterator End; + D.GlobOr(Start,End); // advances D + + if (Cache->IsImportantDep(End) == false) + continue; + + if (Now == true) + { + if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow) + continue; + } + else + { + if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) + continue; + } + + bool FirstOr = true; + while (1) + { + if (First == false) + for (unsigned J = 0; J != Indent; J++) + out << ' '; + First = false; + + if (FirstOr == false) + { + for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++) + out << ' '; + } + else + out << ' ' << End.DepType() << ": "; + FirstOr = false; + + out << Start.TargetPkg().FullName(true); + + // Show a quick summary of the version requirements + if (Start.TargetVer() != 0) + out << " (" << Start.CompType() << " " << Start.TargetVer() << ")"; + + /* Show a summary of the target package if possible. In the case + of virtual packages we show nothing */ + pkgCache::PkgIterator Targ = Start.TargetPkg(); + if (Targ->ProvidesList == 0) + { + out << ' '; + pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache); + if (Now == true) + Ver = Targ.CurrentVer(); + + if (Ver.end() == false) + { + if (Now == true) + ioprintf(out,_("but %s is installed"),Ver.VerStr()); + else + ioprintf(out,_("but %s is to be installed"),Ver.VerStr()); + } + else + { + if (Cache[Targ].CandidateVerIter(Cache).end() == true) + { + if (Targ->ProvidesList == 0) + out << _("but it is not installable"); + else + out << _("but it is a virtual package"); + } + else + out << (Now?_("but it is not installed"):_("but it is not going to be installed")); + } + } + + if (Start != End) + out << _(" or"); + out << endl; + + if (Start == End) + break; + ++Start; + } + } + } +} + /*}}}*/ +// ShowNew - Show packages to newly install /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void ShowNew(ostream &out,CacheFile &Cache) +{ + /* Print out a list of packages that are going to be installed extra + to what the user asked */ + string List; + string VersionsList; + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator I(Cache,Cache.List[J]); + if (Cache[I].NewInstall() == true) { + List += I.FullName(true) + " "; + VersionsList += string(Cache[I].CandVersion) + "\n"; + } + } + + ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList); +} + /*}}}*/ +// ShowDel - Show packages to delete /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void ShowDel(ostream &out,CacheFile &Cache) +{ + /* Print out a list of packages that are going to be removed extra + to what the user asked */ + string List; + string VersionsList; + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator I(Cache,Cache.List[J]); + if (Cache[I].Delete() == true) + { + if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) + List += I.FullName(true) + "* "; + else + List += I.FullName(true) + " "; + + VersionsList += string(Cache[I].CandVersion)+ "\n"; + } + } + + ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList); +} + /*}}}*/ +// ShowKept - Show kept packages /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void ShowKept(ostream &out,CacheFile &Cache) +{ + string List; + string VersionsList; + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator I(Cache,Cache.List[J]); + + // Not interesting + if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false || + I->CurrentVer == 0 || Cache[I].Delete() == true) + continue; + + List += I.FullName(true) + " "; + VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; + } + ShowList(out,_("The following packages have been kept back:"),List,VersionsList); +} + /*}}}*/ +// ShowUpgraded - Show upgraded packages /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void ShowUpgraded(ostream &out,CacheFile &Cache) +{ + string List; + string VersionsList; + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator I(Cache,Cache.List[J]); + + // Not interesting + if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) + continue; + + List += I.FullName(true) + " "; + VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; + } + ShowList(out,_("The following packages will be upgraded:"),List,VersionsList); +} + /*}}}*/ +// ShowDowngraded - Show downgraded packages /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool ShowDowngraded(ostream &out,CacheFile &Cache) +{ + string List; + string VersionsList; + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator I(Cache,Cache.List[J]); + + // Not interesting + if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true) + continue; + + List += I.FullName(true) + " "; + VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; + } + return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList); +} + /*}}}*/ +// ShowHold - Show held but changed packages /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool ShowHold(ostream &out,CacheFile &Cache) +{ + string List; + string VersionsList; + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator I(Cache,Cache.List[J]); + if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() && + I->SelectedState == pkgCache::State::Hold) { + List += I.FullName(true) + " "; + VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; + } + } + + return ShowList(out,_("The following held packages will be changed:"),List,VersionsList); +} + /*}}}*/ +// ShowEssential - Show an essential package warning /*{{{*/ +// --------------------------------------------------------------------- +/* This prints out a warning message that is not to be ignored. It shows + all essential packages and their dependents that are to be removed. + It is insanely risky to remove the dependents of an essential package! */ +bool ShowEssential(ostream &out,CacheFile &Cache) +{ + string List; + string VersionsList; + bool *Added = new bool[Cache->Head().PackageCount]; + for (unsigned int I = 0; I != Cache->Head().PackageCount; I++) + Added[I] = false; + + for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + { + pkgCache::PkgIterator I(Cache,Cache.List[J]); + if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential && + (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important) + continue; + + // The essential package is being removed + if (Cache[I].Delete() == true) + { + if (Added[I->ID] == false) + { + Added[I->ID] = true; + List += I.FullName(true) + " "; + //VersionsList += string(Cache[I].CurVersion) + "\n"; ??? + } + } + else + continue; + + if (I->CurrentVer == 0) + continue; + + // Print out any essential package depenendents that are to be removed + for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D) + { + // Skip everything but depends + if (D->Type != pkgCache::Dep::PreDepends && + D->Type != pkgCache::Dep::Depends) + continue; + + pkgCache::PkgIterator P = D.SmartTargetPkg(); + if (Cache[P].Delete() == true) + { + if (Added[P->ID] == true) + continue; + Added[P->ID] = true; + + char S[300]; + snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str()); + List += S; + //VersionsList += "\n"; ??? + } + } + } + + delete [] Added; + return ShowList(out,_("WARNING: The following essential packages will be removed.\n" + "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList); +} + + /*}}}*/ +// Stats - Show some statistics /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void Stats(ostream &out,pkgDepCache &Dep) +{ + unsigned long Upgrade = 0; + unsigned long Downgrade = 0; + unsigned long Install = 0; + unsigned long ReInstall = 0; + for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I) + { + if (Dep[I].NewInstall() == true) + Install++; + else + { + if (Dep[I].Upgrade() == true) + Upgrade++; + else + if (Dep[I].Downgrade() == true) + Downgrade++; + } + + if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall) + ReInstall++; + } + + ioprintf(out,_("%lu upgraded, %lu newly installed, "), + Upgrade,Install); + + if (ReInstall != 0) + ioprintf(out,_("%lu reinstalled, "),ReInstall); + if (Downgrade != 0) + ioprintf(out,_("%lu downgraded, "),Downgrade); + + ioprintf(out,_("%lu to remove and %lu not upgraded.\n"), + Dep.DelCount(),Dep.KeepCount()); + + if (Dep.BadCount() != 0) + ioprintf(out,_("%lu not fully installed or removed.\n"), + Dep.BadCount()); +} + /*}}}*/ +// YnPrompt - Yes No Prompt. /*{{{*/ +// --------------------------------------------------------------------- +/* Returns true on a Yes.*/ +bool YnPrompt(bool Default) +{ + /* nl_langinfo does not support LANGUAGE setting, so we unset it here + to have the help-message (hopefully) match the expected characters */ + char * language = getenv("LANGUAGE"); + if (language != NULL) + language = strdup(language); + if (language != NULL) + unsetenv("LANGUAGE"); + + if (Default == true) + // TRANSLATOR: Yes/No question help-text: defaulting to Y[es] + // e.g. "Do you want to continue? [Y/n] " + // The user has to answer with an input matching the + // YESEXPR/NOEXPR defined in your l10n. + c2out << " " << _("[Y/n]") << " " << std::flush; + else + // TRANSLATOR: Yes/No question help-text: defaulting to N[o] + // e.g. "Should this file be removed? [y/N] " + // The user has to answer with an input matching the + // YESEXPR/NOEXPR defined in your l10n. + c2out << " " << _("[y/N]") << " " << std::flush; + + if (language != NULL) + { + setenv("LANGUAGE", language, 0); + free(language); + } + + if (_config->FindB("APT::Get::Assume-Yes",false) == true) + { + // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set + c1out << _("Y") << std::endl; + return true; + } + else if (_config->FindB("APT::Get::Assume-No",false) == true) + { + // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set + c1out << _("N") << std::endl; + return false; + } + + char response[1024] = ""; + std::cin.getline(response, sizeof(response)); + + if (!std::cin) + return false; + + if (strlen(response) == 0) + return Default; + + regex_t Pattern; + int Res; + + Res = regcomp(&Pattern, nl_langinfo(YESEXPR), + REG_EXTENDED|REG_ICASE|REG_NOSUB); + + if (Res != 0) { + char Error[300]; + regerror(Res,&Pattern,Error,sizeof(Error)); + return _error->Error(_("Regex compilation error - %s"),Error); + } + + Res = regexec(&Pattern, response, 0, NULL, 0); + if (Res == 0) + return true; + return false; +} + /*}}}*/ +// AnalPrompt - Annoying Yes No Prompt. /*{{{*/ +// --------------------------------------------------------------------- +/* Returns true on a Yes.*/ +bool AnalPrompt(const char *Text) +{ + char Buf[1024]; + std::cin.getline(Buf,sizeof(Buf)); + if (strcmp(Buf,Text) == 0) + return true; + return false; +} + /*}}}*/ diff --git a/apt-private/private-output.h b/apt-private/private-output.h new file mode 100644 index 000000000..9283e39ab --- /dev/null +++ b/apt-private/private-output.h @@ -0,0 +1,49 @@ +#ifndef APT_PRIVATE_OUTPUT_H +#define APT_PRIVATE_OUTPUT_H + + +#include <iostream> +#include <fstream> +#include <string> + +#include "private-cachefile.h" + +// forward declaration +class pkgCacheFile; +class CacheFile; +class pkgCache; +class pkgDepCache; +class pkgRecords; + + +extern std::ostream c0out; +extern std::ostream c1out; +extern std::ostream c2out; +extern std::ofstream devnull; +extern unsigned int ScreenWidth; + +bool InitOutput(); +void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, + pkgCache::VerIterator V, std::ostream &out); + + + +bool ShowList(std::ostream &out, std::string Title, std::string List, + std::string VersionsList); +void ShowBroken(std::ostream &out,CacheFile &Cache,bool Now); +void ShowNew(std::ostream &out,CacheFile &Cache); +void ShowDel(std::ostream &out,CacheFile &Cache); +void ShowKept(std::ostream &out,CacheFile &Cache); +void ShowUpgraded(std::ostream &out,CacheFile &Cache); +bool ShowDowngraded(std::ostream &out,CacheFile &Cache); +bool ShowHold(std::ostream &out,CacheFile &Cache); + +bool ShowEssential(std::ostream &out,CacheFile &Cache); + +void Stats(std::ostream &out, pkgDepCache &Dep); + +// prompting +bool YnPrompt(bool Default=true); +bool AnalPrompt(const char *Text); + +#endif diff --git a/apt-private/private-search.cc b/apt-private/private-search.cc new file mode 100644 index 000000000..6881f482f --- /dev/null +++ b/apt-private/private-search.cc @@ -0,0 +1,99 @@ +#include <apt-pkg/error.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/cachefilter.h> +#include <apt-pkg/cacheset.h> +#include <apt-pkg/init.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/pkgrecords.h> +#include <apt-pkg/srcrecords.h> +#include <apt-pkg/version.h> +#include <apt-pkg/policy.h> +#include <apt-pkg/tagfile.h> +#include <apt-pkg/algorithms.h> +#include <apt-pkg/sptr.h> +#include <apt-pkg/pkgsystem.h> +#include <apt-pkg/indexfile.h> +#include <apt-pkg/metaindex.h> + +#include <sstream> +#include <utility> +#include <cassert> +#include <locale.h> +#include <iostream> +#include <unistd.h> +#include <errno.h> +#include <regex.h> +#include <stdio.h> +#include <iomanip> +#include <algorithm> +#include <map> + +#include "private-search.h" +#include "private-cacheset.h" + + +bool FullTextSearch(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + pkgCache *Cache = CacheFile.GetPkgCache(); + pkgDepCache::Policy *Plcy = CacheFile.GetPolicy(); + pkgRecords records(CacheFile); + if (unlikely(Cache == NULL || Plcy == NULL)) + return false; + + const char **patterns; + patterns = CmdL.FileList + 1; + + std::map<std::string, std::string> output_map; + std::map<std::string, std::string>::const_iterator K; + + LocalitySortedVersionSet bag; + OpTextProgress progress; + progress.OverallProgress(0, 100, 50, _("Sorting")); + GetLocalitySortedVersionSet(CacheFile, bag, progress); + LocalitySortedVersionSet::iterator V = bag.begin(); + + progress.OverallProgress(50, 100, 50, _("Full Text Search")); + progress.SubProgress(bag.size()); + int Done = 0; + for ( ;V != bag.end(); V++) + { + if (Done%500 == 0) + progress.Progress(Done); + Done++; + + int i; + pkgCache::DescIterator Desc = V.TranslatedDescription(); + pkgRecords::Parser &parser = records.Lookup(Desc.FileList()); + + bool all_found = true; + for(i=0; patterns[i] != NULL; i++) + { + // FIXME: use regexp instead of simple find() + const char *pattern = patterns[i]; + all_found &= ( + strstr(V.ParentPkg().Name(), pattern) != NULL || + parser.ShortDesc().find(pattern) != std::string::npos || + parser.LongDesc().find(pattern) != std::string::npos); + } + if (all_found) + { + std::stringstream outs; + ListSingleVersion(CacheFile, records, V, outs); + output_map.insert(std::make_pair<std::string, std::string>( + V.ParentPkg().Name(), outs.str())); + } + } + progress.Done(); + + // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status) + // output the sorted map + for (K = output_map.begin(); K != output_map.end(); K++) + std::cout << (*K).second << std::endl; + + return true; +} diff --git a/apt-private/private-search.h b/apt-private/private-search.h new file mode 100644 index 000000000..17faffebc --- /dev/null +++ b/apt-private/private-search.h @@ -0,0 +1,9 @@ +#ifndef APT_PRIVATE_SEARCH_H +#define APT_PRIVATE_SEARCH_H + +#include <apt-pkg/cmndline.h> + +bool FullTextSearch(CommandLine &CmdL); + + +#endif diff --git a/apt-private/private-show.cc b/apt-private/private-show.cc new file mode 100644 index 000000000..e26a2b30a --- /dev/null +++ b/apt-private/private-show.cc @@ -0,0 +1,122 @@ +#include <apt-pkg/error.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/cachefilter.h> +#include <apt-pkg/cacheset.h> +#include <apt-pkg/init.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/pkgrecords.h> +#include <apt-pkg/srcrecords.h> +#include <apt-pkg/version.h> +#include <apt-pkg/policy.h> +#include <apt-pkg/tagfile.h> +#include <apt-pkg/algorithms.h> +#include <apt-pkg/sptr.h> +#include <apt-pkg/pkgsystem.h> +#include <apt-pkg/indexfile.h> +#include <apt-pkg/metaindex.h> + +#include <apti18n.h> + +#include "private-output.h" +#include "private-cacheset.h" + +namespace APT { + namespace Cmd { + +// DisplayRecord - Displays the complete record for the package /*{{{*/ +// --------------------------------------------------------------------- +bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V, + ostream &out) +{ + pkgCache *Cache = CacheFile.GetPkgCache(); + if (unlikely(Cache == NULL)) + return false; + + // Find an appropriate file + pkgCache::VerFileIterator Vf = V.FileList(); + for (; Vf.end() == false; ++Vf) + if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0) + break; + if (Vf.end() == true) + Vf = V.FileList(); + + // Check and load the package list file + pkgCache::PkgFileIterator I = Vf.File(); + if (I.IsOk() == false) + return _error->Error(_("Package file %s is out of sync."),I.FileName()); + + // Read the record + FileFd PkgF; + if (PkgF.Open(I.FileName(), FileFd::ReadOnly, FileFd::Extension) == false) + return false; + pkgTagSection Tags; + pkgTagFile TagF(&PkgF); + + TFRewriteData RW[] = { + {"Conffiles",0}, + {"Description",0}, + {"Description-md5",0}, + {} + }; + const char *Zero = 0; + if (TagF.Jump(Tags, V.FileList()->Offset) == false || + TFRewrite(stdout,Tags,&Zero,RW) == false) + { + _error->Error("Internal Error, Unable to parse a package record"); + return false; + } + + // write the description + pkgRecords Recs(*Cache); + pkgCache::DescIterator Desc = V.TranslatedDescription(); + if (Desc.end() == false) + { + pkgRecords::Parser &P = Recs.Lookup(Desc.FileList()); + if (strcmp(Desc.LanguageCode(),"") != 0) + out << "Description-lang: " << Desc.LanguageCode() << std::endl; + out << "Description" << P.LongDesc(); + } + + // write a final newline (after the description) + out << std::endl << std::endl; + + return true; +} + /*}}}*/ + +bool ShowPackage(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + CacheSetHelperVirtuals helper(true, GlobalError::NOTICE); + APT::VersionList::Version const select = APT::VersionList::CANDIDATE; + APT::VersionList const verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, select, helper); + for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver) + if (DisplayRecord(CacheFile, Ver, c1out) == false) + return false; + + for (APT::PackageSet::const_iterator Pkg = helper.virtualPkgs.begin(); + Pkg != helper.virtualPkgs.end(); ++Pkg) + { + c1out << "Package: " << Pkg.FullName(true) << std::endl; + c1out << "State: " << _("not a real pacakge (virtual)") << std::endl; + // FIXME: show providers, see private-cacheset.h + // CacheSetHelperAPTGet::showVirtualPackageErrors() + } + + if (verset.empty() == true) + { + if (helper.virtualPkgs.empty() == true) + return _error->Error(_("No packages found")); + else + _error->Notice(_("No packages found")); + } + + return true; +} + /*}}}*/ +} // namespace Cmd +} // namespace APT diff --git a/apt-private/private-show.h b/apt-private/private-show.h new file mode 100644 index 000000000..b428c7af0 --- /dev/null +++ b/apt-private/private-show.h @@ -0,0 +1,12 @@ +#ifndef APT_PRIVATE_SHOW_H +#define APT_PRIVATE_SHOW_H + +#include <apt-pkg/cmndline.h> + +namespace APT { + namespace Cmd { + + bool ShowPackage(CommandLine &CmdL); + } +} +#endif diff --git a/apt-private/private-update.cc b/apt-private/private-update.cc new file mode 100644 index 000000000..61259748d --- /dev/null +++ b/apt-private/private-update.cc @@ -0,0 +1,93 @@ +// Include files /*{{{*/ +#include<config.h> + +#include <apt-pkg/aptconfiguration.h> +#include <apt-pkg/error.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/init.h> +#include <apt-pkg/depcache.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/algorithms.h> +#include <apt-pkg/acquire-item.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/clean.h> +#include <apt-pkg/srcrecords.h> +#include <apt-pkg/version.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/cacheset.h> +#include <apt-pkg/sptr.h> +#include <apt-pkg/md5.h> +#include <apt-pkg/versionmatch.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/pkgsystem.h> +#include <apt-pkg/pkgrecords.h> +#include <apt-pkg/indexfile.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "private-cachefile.h" +#include "private-output.h" +#include "acqprogress.h" + +#include <apti18n.h> + /*}}}*/ + +// DoUpdate - Update the package lists /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool DoUpdate(CommandLine &CmdL) +{ + if (CmdL.FileSize() != 1) + return _error->Error(_("The update command takes no arguments")); + + CacheFile Cache; + + // Get the source list + if (Cache.BuildSourceList() == false) + return false; + pkgSourceList *List = Cache.GetSourceList(); + + // Create the progress + AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); + + // Just print out the uris an exit if the --print-uris flag was used + if (_config->FindB("APT::Get::Print-URIs") == true) + { + // force a hashsum for compatibility reasons + _config->CndSet("Acquire::ForceHash", "md5sum"); + + // get a fetcher + pkgAcquire Fetcher; + if (Fetcher.Setup(&Stat) == false) + return false; + + // Populate it with the source selection and get all Indexes + // (GetAll=true) + if (List->GetIndexes(&Fetcher,true) == false) + return false; + + pkgAcquire::UriIterator I = Fetcher.UriBegin(); + for (; I != Fetcher.UriEnd(); ++I) + c1out << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << + I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl; + return true; + } + + // do the work + if (_config->FindB("APT::Get::Download",true) == true) + ListUpdate(Stat, *List); + + // Rebuild the cache. + if (_config->FindB("pkgCacheFile::Generate", true) == true) + { + pkgCacheFile::RemoveCaches(); + if (Cache.BuildCaches() == false) + return false; + } + + return true; +} + /*}}}*/ diff --git a/apt-private/private-update.h b/apt-private/private-update.h new file mode 100644 index 000000000..d3d0b7af9 --- /dev/null +++ b/apt-private/private-update.h @@ -0,0 +1,8 @@ +#ifndef APT_PRIVATE_UPDATE_H +#define APT_PRIVATE_UPDATE_H + +class CommandLine; + +bool DoUpdate(CommandLine &CmdL); + +#endif diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc new file mode 100644 index 000000000..85b5a492a --- /dev/null +++ b/apt-private/private-upgrade.cc @@ -0,0 +1,47 @@ + +#include <apt-pkg/algorithms.h> + +#include "private-install.h" +#include "private-cachefile.h" +#include "private-upgrade.h" +#include "private-output.h" + + +// DoUpgradeNoNewPackages - Upgrade all packages /*{{{*/ +// --------------------------------------------------------------------- +/* Upgrade all packages without installing new packages or erasing old + packages */ +bool DoUpgradeNoNewPackages(CommandLine &CmdL) +{ + CacheFile Cache; + if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) + return false; + + // Do the upgrade + if (pkgAllUpgrade(Cache) == false) + { + ShowBroken(c1out,Cache,false); + return _error->Error(_("Internal error, AllUpgrade broke stuff")); + } + + return InstallPackages(Cache,true); +} + /*}}}*/ + +// DoSafeUpgrade - Upgrade all packages with install but not remove /*{{{*/ +bool DoUpgradeWithAllowNewPackages(CommandLine &CmdL) +{ + CacheFile Cache; + if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) + return false; + + // Do the upgrade + if (pkgAllUpgradeNoDelete(Cache) == false) + { + ShowBroken(c1out,Cache,false); + return _error->Error(_("Internal error, AllUpgrade broke stuff")); + } + + return InstallPackages(Cache,true); +} + /*}}}*/ diff --git a/apt-private/private-upgrade.h b/apt-private/private-upgrade.h new file mode 100644 index 000000000..6ede6f96c --- /dev/null +++ b/apt-private/private-upgrade.h @@ -0,0 +1,11 @@ +#ifndef APTPRIVATE_PRIVATE_UPGRADE_H +#define APTPRIVATE_PRIVATE_UPGRADE_H + +#include <apt-pkg/cmndline.h> + + +bool DoUpgradeNoNewPackages(CommandLine &CmdL); +bool DoUpgradeWithAllowNewPackages(CommandLine &CmdL); + + +#endif diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index e847de875..b8892d23d 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -35,6 +35,11 @@ #include <apt-pkg/indexfile.h> #include <apt-pkg/metaindex.h> +#include <apt-private/private-list.h> +#include <apt-private/private-cmndline.h> +#include <apt-private/private-show.h> +#include <apt-private/private-cacheset.h> + #include <cassert> #include <locale.h> #include <iostream> @@ -50,29 +55,6 @@ using namespace std; -// CacheSetHelper saving virtual packages /*{{{*/ -class CacheSetHelperVirtuals: public APT::CacheSetHelper { -public: - APT::PackageSet virtualPkgs; - - virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { - virtualPkgs.insert(Pkg); - return CacheSetHelper::canNotFindCandidateVer(Cache, Pkg); - } - - virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { - virtualPkgs.insert(Pkg); - return CacheSetHelper::canNotFindNewestVer(Cache, Pkg); - } - - virtual void canNotFindAllVer(APT::VersionContainerInterface * vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { - virtualPkgs.insert(Pkg); - CacheSetHelper::canNotFindAllVer(vci, Cache, Pkg); - } - - CacheSetHelperVirtuals(bool const ShowErrors = true, GlobalError::MsgType const &ErrorType = GlobalError::NOTICE) : CacheSetHelper(ShowErrors, ErrorType) {} -}; - /*}}}*/ // LocalitySort - Sort a version list by package file locality /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -396,42 +378,42 @@ bool Dump(CommandLine &Cmd) if (unlikely(Cache == NULL)) return false; - cout << "Using Versioning System: " << Cache->VS->Label << endl; + std::cout << "Using Versioning System: " << Cache->VS->Label << std::endl; for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P) { - cout << "Package: " << P.FullName(true) << endl; + std::cout << "Package: " << P.FullName(true) << std::endl; for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V) { - cout << " Version: " << V.VerStr() << endl; - cout << " File: " << V.FileList().File().FileName() << endl; + std::cout << " Version: " << V.VerStr() << std::endl; + std::cout << " File: " << V.FileList().File().FileName() << std::endl; for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D) - cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' << - DeNull(D.TargetVer()) << endl; + std::cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' << + DeNull(D.TargetVer()) << std::endl; for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D) { - cout << " Description Language: " << D.LanguageCode() << endl - << " File: " << D.FileList().File().FileName() << endl - << " MD5: " << D.md5() << endl; + std::cout << " Description Language: " << D.LanguageCode() << std::endl + << " File: " << D.FileList().File().FileName() << std::endl + << " MD5: " << D.md5() << std::endl; } } } for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F) { - cout << "File: " << F.FileName() << endl; - cout << " Type: " << F.IndexType() << endl; - cout << " Size: " << F->Size << endl; - cout << " ID: " << F->ID << endl; - cout << " Flags: " << F->Flags << endl; - cout << " Time: " << TimeRFC1123(F->mtime) << endl; - cout << " Archive: " << DeNull(F.Archive()) << endl; - cout << " Component: " << DeNull(F.Component()) << endl; - cout << " Version: " << DeNull(F.Version()) << endl; - cout << " Origin: " << DeNull(F.Origin()) << endl; - cout << " Site: " << DeNull(F.Site()) << endl; - cout << " Label: " << DeNull(F.Label()) << endl; - cout << " Architecture: " << DeNull(F.Architecture()) << endl; + std::cout << "File: " << F.FileName() << std::endl; + std::cout << " Type: " << F.IndexType() << std::endl; + std::cout << " Size: " << F->Size << std::endl; + std::cout << " ID: " << F->ID << std::endl; + std::cout << " Flags: " << F->Flags << std::endl; + std::cout << " Time: " << TimeRFC1123(F->mtime) << std::endl; + std::cout << " Archive: " << DeNull(F.Archive()) << std::endl; + std::cout << " Component: " << DeNull(F.Component()) << std::endl; + std::cout << " Version: " << DeNull(F.Version()) << std::endl; + std::cout << " Origin: " << DeNull(F.Origin()) << std::endl; + std::cout << " Site: " << DeNull(F.Site()) << std::endl; + std::cout << " Label: " << DeNull(F.Label()) << std::endl; + std::cout << " Architecture: " << DeNull(F.Architecture()) << std::endl; } return true; @@ -627,8 +609,7 @@ bool ShowDepends(CommandLine &CmdL, bool const RevDepends) case pkgCache::Dep::Depends: if (!ShowDepends) continue; break; case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break; case pkgCache::Dep::Suggests: if (!ShowSuggests) continue; break; - case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break; - case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break; + case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break; case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break; case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break; case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break; } @@ -1238,7 +1219,6 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V) return true; } /*}}}*/ - struct ExDescFile { pkgCache::DescFile *Df; @@ -1795,38 +1775,10 @@ bool ShowHelp(CommandLine &Cmd) /*}}}*/ int main(int argc,const char *argv[]) /*{{{*/ { - CommandLine::Args Args[] = { - {'h',"help","help",0}, - {'v',"version","version",0}, - {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg}, - {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg}, - {'q',"quiet","quiet",CommandLine::IntLevel}, - {'i',"important","APT::Cache::Important",0}, - {'f',"full","APT::Cache::ShowFull",0}, - {'g',"generate","APT::Cache::Generate",0}, - {'a',"all-versions","APT::Cache::AllVersions",0}, - {'n',"names-only","APT::Cache::NamesOnly",0}, - {0,"all-names","APT::Cache::AllNames",0}, - {0,"recurse","APT::Cache::RecurseDepends",0}, - {'t',"target-release","APT::Default-Release",CommandLine::HasArg}, - {'t',"default-release","APT::Default-Release",CommandLine::HasArg}, - {'c',"config-file",0,CommandLine::ConfigFile}, - {'o',"option",0,CommandLine::ArbItem}, - {0,"installed","APT::Cache::Installed",0}, - {0,"pre-depends","APT::Cache::ShowPre-Depends",0}, - {0,"depends","APT::Cache::ShowDepends",0}, - {0,"recommends","APT::Cache::ShowRecommends",0}, - {0,"suggests","APT::Cache::ShowSuggests",0}, - {0,"replaces","APT::Cache::ShowReplaces",0}, - {0,"breaks","APT::Cache::ShowBreaks",0}, - {0,"conflicts","APT::Cache::ShowConflicts",0}, - {0,"enhances","APT::Cache::ShowEnhances",0}, - {0,0,0,0}}; - CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp}, + CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp}, {"gencaches",&GenCaches}, {"showsrc",&ShowSrcPackage}, - {0,0}}; - CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage}, + {"showpkg",&DumpPackage}, {"stats",&Stats}, {"dump",&Dump}, {"dumpavail",&DumpAvail}, @@ -1843,12 +1795,14 @@ int main(int argc,const char *argv[]) /*{{{*/ {"madison",&Madison}, {0,0}}; + std::vector<CommandLine::Args> Args = getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds, argc, argv)); + // Set up gettext support setlocale(LC_ALL,""); textdomain(PACKAGE); // Parse the command line and initialize the package library - CommandLine CmdL(Args,_config); + CommandLine CmdL(Args.data(),_config); if (pkgInitConfig(*_config) == false || CmdL.Parse(argc,argv) == false || pkgInitSystem(*_config,_system) == false) @@ -1872,8 +1826,8 @@ int main(int argc,const char *argv[]) /*{{{*/ if (_config->Exists("APT::Cache::Generate") == true) _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true)); - if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false) - CmdL.DispatchArg(CmdsB); + // Match the operation + CmdL.DispatchArg(Cmds); // Print any errors or warnings found during parsing bool const Errors = _error->PendingError(); diff --git a/cmdline/apt-cdrom.cc b/cmdline/apt-cdrom.cc index a95970782..17a60ddcb 100644 --- a/cmdline/apt-cdrom.cc +++ b/cmdline/apt-cdrom.cc @@ -37,6 +37,8 @@ #include <unistd.h> #include <stdio.h> +#include <apt-private/private-cmndline.h> + #include <apti18n.h> /*}}}*/ static const char *W_NO_CDROM_FOUND = \ @@ -203,12 +205,12 @@ bool DoIdent(CommandLine &) // ShowHelp - Show the help screen /*{{{*/ // --------------------------------------------------------------------- /* */ -int ShowHelp() +bool ShowHelp(CommandLine &) { ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION, COMMON_ARCH,__DATE__,__TIME__); if (_config->FindB("version") == true) - return 0; + return true; cout << "Usage: apt-cdrom [options] command\n" @@ -232,37 +234,25 @@ int ShowHelp() " -c=? Read this configuration file\n" " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n" "See fstab(5)\n"; - return 0; + return true; } /*}}}*/ int main(int argc,const char *argv[]) /*{{{*/ { - CommandLine::Args Args[] = { - {'h',"help","help",0}, - { 0,"auto-detect","Acquire::cdrom::AutoDetect", CommandLine::Boolean}, - {'v',"version","version",0}, - {'d',"cdrom","Acquire::cdrom::mount",CommandLine::HasArg}, - {'r',"rename","APT::CDROM::Rename",0}, - {'m',"no-mount","APT::CDROM::NoMount",0}, - {'f',"fast","APT::CDROM::Fast",0}, - {'n',"just-print","APT::CDROM::NoAct",0}, - {'n',"recon","APT::CDROM::NoAct",0}, - {'n',"no-act","APT::CDROM::NoAct",0}, - {'a',"thorough","APT::CDROM::Thorough",0}, - {'c',"config-file",0,CommandLine::ConfigFile}, - {'o',"option",0,CommandLine::ArbItem}, - {0,0,0,0}}; CommandLine::Dispatch Cmds[] = { {"add",&DoAdd}, {"ident",&DoIdent}, + {"help",&ShowHelp}, {0,0}}; + std::vector<CommandLine::Args> Args = getCommandArgs("apt-cdrom", CommandLine::GetCommand(Cmds, argc, argv)); + // Set up gettext support setlocale(LC_ALL,""); textdomain(PACKAGE); // Parse the command line and initialize the package library - CommandLine CmdL(Args,_config); + CommandLine CmdL(Args.data(),_config); if (pkgInitConfig(*_config) == false || CmdL.Parse(argc,argv) == false || pkgInitSystem(*_config,_system) == false) @@ -274,7 +264,7 @@ int main(int argc,const char *argv[]) /*{{{*/ // See if the help should be shown if (_config->FindB("help") == true || _config->FindB("version") == true || CmdL.FileSize() == 0) - return ShowHelp(); + return ShowHelp(CmdL); // Deal with stdout not being a tty if (isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) diff --git a/cmdline/apt-config.cc b/cmdline/apt-config.cc index 397ce32df..3481eaf5f 100644 --- a/cmdline/apt-config.cc +++ b/cmdline/apt-config.cc @@ -31,6 +31,8 @@ #include <string> #include <vector> +#include <apt-private/private-cmndline.h> + #include <apti18n.h> /*}}}*/ using namespace std; @@ -76,12 +78,12 @@ bool DoDump(CommandLine &CmdL) // ShowHelp - Show the help screen /*{{{*/ // --------------------------------------------------------------------- /* */ -int ShowHelp() +bool ShowHelp(CommandLine &CmdL) { ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION, COMMON_ARCH,__DATE__,__TIME__); if (_config->FindB("version") == true) - return 0; + return true; cout << _("Usage: apt-config [options] command\n" @@ -96,29 +98,24 @@ int ShowHelp() " -h This help text.\n" " -c=? Read this configuration file\n" " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"); - return 0; + return true; } /*}}}*/ int main(int argc,const char *argv[]) /*{{{*/ { - CommandLine::Args Args[] = { - {'h',"help","help",0}, - {'v',"version","version",0}, - {'c',"config-file",0,CommandLine::ConfigFile}, - {'o',"option",0,CommandLine::ArbItem}, - {0,"empty","APT::Config::Dump::EmptyValue",CommandLine::Boolean}, - {0,"format","APT::Config::Dump::Format",CommandLine::HasArg}, - {0,0,0,0}}; CommandLine::Dispatch Cmds[] = {{"shell",&DoShell}, {"dump",&DoDump}, + {"help",&ShowHelp}, {0,0}}; + std::vector<CommandLine::Args> Args = getCommandArgs("apt-cdrom", CommandLine::GetCommand(Cmds, argc, argv)); + // Set up gettext support setlocale(LC_ALL,""); textdomain(PACKAGE); // Parse the command line and initialize the package library - CommandLine CmdL(Args,_config); + CommandLine CmdL(Args.data(),_config); if (pkgInitConfig(*_config) == false || CmdL.Parse(argc,argv) == false || pkgInitSystem(*_config,_system) == false) @@ -130,7 +127,7 @@ int main(int argc,const char *argv[]) /*{{{*/ // See if the help should be shown if (_config->FindB("help") == true || CmdL.FileSize() == 0) - return ShowHelp(); + return ShowHelp(CmdL); std::vector<std::string> const langs = APT::Configuration::getLanguages(true); _config->Clear("Acquire::Languages"); diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 4b7691d93..06dbbce5b 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -50,7 +50,16 @@ #include <apt-pkg/pkgrecords.h> #include <apt-pkg/indexfile.h> -#include "acqprogress.h" + +#include <apt-private/private-install.h> +#include <apt-private/private-upgrade.h> +#include <apt-private/private-output.h> +#include <apt-private/private-cacheset.h> +#include <apt-private/private-update.h> +#include <apt-private/private-cmndline.h> +#include <apt-private/private-moo.h> + +#include <apt-private/acqprogress.h> #include <set> #include <locale.h> @@ -69,1391 +78,17 @@ #include <sys/wait.h> #include <sstream> +#include <apt-private/private-output.h> +#include <apt-private/private-main.h> + #include <apti18n.h> /*}}}*/ -#define RAMFS_MAGIC 0x858458f6 using namespace std; -ostream c0out(0); -ostream c1out(0); -ostream c2out(0); -ofstream devnull("/dev/null"); -unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */ - -// class CacheFile - Cover class for some dependency cache functions /*{{{*/ -// --------------------------------------------------------------------- -/* */ -class CacheFile : public pkgCacheFile -{ - static pkgCache *SortCache; - static int NameComp(const void *a,const void *b); - - public: - pkgCache::Package **List; - - void Sort(); - bool CheckDeps(bool AllowBroken = false); - bool BuildCaches(bool WithLock = true) - { - OpTextProgress Prog(*_config); - if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false) - return false; - return true; - } - bool Open(bool WithLock = true) - { - OpTextProgress Prog(*_config); - if (pkgCacheFile::Open(&Prog,WithLock) == false) - return false; - Sort(); - - return true; - }; - bool OpenForInstall() - { - if (_config->FindB("APT::Get::Print-URIs") == true) - return Open(false); - else - return Open(true); - } - CacheFile() : List(0) {}; - ~CacheFile() { - delete[] List; - } -}; - /*}}}*/ - -// YnPrompt - Yes No Prompt. /*{{{*/ -// --------------------------------------------------------------------- -/* Returns true on a Yes.*/ -bool YnPrompt(bool Default=true) -{ - /* nl_langinfo does not support LANGUAGE setting, so we unset it here - to have the help-message (hopefully) match the expected characters */ - char * language = getenv("LANGUAGE"); - if (language != NULL) - language = strdup(language); - if (language != NULL) - unsetenv("LANGUAGE"); - - if (Default == true) - // TRANSLATOR: Yes/No question help-text: defaulting to Y[es] - // e.g. "Do you want to continue? [Y/n] " - // The user has to answer with an input matching the - // YESEXPR/NOEXPR defined in your l10n. - c2out << " " << _("[Y/n]") << " " << std::flush; - else - // TRANSLATOR: Yes/No question help-text: defaulting to N[o] - // e.g. "Should this file be removed? [y/N] " - // The user has to answer with an input matching the - // YESEXPR/NOEXPR defined in your l10n. - c2out << " " << _("[y/N]") << " " << std::flush; - - if (language != NULL) - { - setenv("LANGUAGE", language, 0); - free(language); - } - - if (_config->FindB("APT::Get::Assume-Yes",false) == true) - { - // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set - c1out << _("Y") << endl; - return true; - } - else if (_config->FindB("APT::Get::Assume-No",false) == true) - { - // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set - c1out << _("N") << endl; - return false; - } - - char response[1024] = ""; - cin.getline(response, sizeof(response)); - - if (!cin) - return false; - - if (strlen(response) == 0) - return Default; - - regex_t Pattern; - int Res; - - Res = regcomp(&Pattern, nl_langinfo(YESEXPR), - REG_EXTENDED|REG_ICASE|REG_NOSUB); - - if (Res != 0) { - char Error[300]; - regerror(Res,&Pattern,Error,sizeof(Error)); - return _error->Error(_("Regex compilation error - %s"),Error); - } - - Res = regexec(&Pattern, response, 0, NULL, 0); - if (Res == 0) - return true; - return false; -} - /*}}}*/ -// AnalPrompt - Annoying Yes No Prompt. /*{{{*/ -// --------------------------------------------------------------------- -/* Returns true on a Yes.*/ -bool AnalPrompt(const char *Text) -{ - char Buf[1024]; - cin.getline(Buf,sizeof(Buf)); - if (strcmp(Buf,Text) == 0) - return true; - return false; -} - /*}}}*/ -// ShowList - Show a list /*{{{*/ -// --------------------------------------------------------------------- -/* This prints out a string of space separated words with a title and - a two space indent line wraped to the current screen width. */ -bool ShowList(ostream &out,string Title,string List,string VersionsList) -{ - if (List.empty() == true) - return true; - // trim trailing space - int NonSpace = List.find_last_not_of(' '); - if (NonSpace != -1) - { - List = List.erase(NonSpace + 1); - if (List.empty() == true) - return true; - } - - // Acount for the leading space - int ScreenWidth = ::ScreenWidth - 3; - - out << Title << endl; - string::size_type Start = 0; - string::size_type VersionsStart = 0; - while (Start < List.size()) - { - if(_config->FindB("APT::Get::Show-Versions",false) == true && - VersionsList.size() > 0) { - string::size_type End; - string::size_type VersionsEnd; - - End = List.find(' ',Start); - VersionsEnd = VersionsList.find('\n', VersionsStart); - - out << " " << string(List,Start,End - Start) << " (" << - string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) << - ")" << endl; - - if (End == string::npos || End < Start) - End = Start + ScreenWidth; - - Start = End + 1; - VersionsStart = VersionsEnd + 1; - } else { - string::size_type End; - - if (Start + ScreenWidth >= List.size()) - End = List.size(); - else - End = List.rfind(' ',Start+ScreenWidth); - - if (End == string::npos || End < Start) - End = Start + ScreenWidth; - out << " " << string(List,Start,End - Start) << endl; - Start = End + 1; - } - } - - return false; -} - /*}}}*/ -// ShowBroken - Debugging aide /*{{{*/ -// --------------------------------------------------------------------- -/* This prints out the names of all the packages that are broken along - with the name of each each broken dependency and a quite version - description. - - The output looks like: - The following packages have unmet dependencies: - exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed - Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed - Depends: libsasl7 but it is not going to be installed - */ -void ShowBroken(ostream &out,CacheFile &Cache,bool Now) -{ - if (Cache->BrokenCount() == 0) - return; - - out << _("The following packages have unmet dependencies:") << endl; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - if (Now == true) - { - if (Cache[I].NowBroken() == false) - continue; - } - else - { - if (Cache[I].InstBroken() == false) - continue; - } - - // Print out each package and the failed dependencies - out << " " << I.FullName(true) << " :"; - unsigned const Indent = I.FullName(true).size() + 3; - bool First = true; - pkgCache::VerIterator Ver; - - if (Now == true) - Ver = I.CurrentVer(); - else - Ver = Cache[I].InstVerIter(Cache); - - if (Ver.end() == true) - { - out << endl; - continue; - } - - for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) - { - // Compute a single dependency element (glob or) - pkgCache::DepIterator Start; - pkgCache::DepIterator End; - D.GlobOr(Start,End); // advances D - - if (Cache->IsImportantDep(End) == false) - continue; - - if (Now == true) - { - if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow) - continue; - } - else - { - if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) - continue; - } - - bool FirstOr = true; - while (1) - { - if (First == false) - for (unsigned J = 0; J != Indent; J++) - out << ' '; - First = false; - - if (FirstOr == false) - { - for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++) - out << ' '; - } - else - out << ' ' << End.DepType() << ": "; - FirstOr = false; - - out << Start.TargetPkg().FullName(true); - - // Show a quick summary of the version requirements - if (Start.TargetVer() != 0) - out << " (" << Start.CompType() << " " << Start.TargetVer() << ")"; - - /* Show a summary of the target package if possible. In the case - of virtual packages we show nothing */ - pkgCache::PkgIterator Targ = Start.TargetPkg(); - if (Targ->ProvidesList == 0) - { - out << ' '; - pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache); - if (Now == true) - Ver = Targ.CurrentVer(); - - if (Ver.end() == false) - { - if (Now == true) - ioprintf(out,_("but %s is installed"),Ver.VerStr()); - else - ioprintf(out,_("but %s is to be installed"),Ver.VerStr()); - } - else - { - if (Cache[Targ].CandidateVerIter(Cache).end() == true) - { - if (Targ->ProvidesList == 0) - out << _("but it is not installable"); - else - out << _("but it is a virtual package"); - } - else - out << (Now?_("but it is not installed"):_("but it is not going to be installed")); - } - } - - if (Start != End) - out << _(" or"); - out << endl; - - if (Start == End) - break; - ++Start; - } - } - } -} - /*}}}*/ -// ShowNew - Show packages to newly install /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void ShowNew(ostream &out,CacheFile &Cache) -{ - /* Print out a list of packages that are going to be installed extra - to what the user asked */ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].NewInstall() == true) { - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CandVersion) + "\n"; - } - } - - ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList); -} - /*}}}*/ -// ShowDel - Show packages to delete /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void ShowDel(ostream &out,CacheFile &Cache) -{ - /* Print out a list of packages that are going to be removed extra - to what the user asked */ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].Delete() == true) - { - if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) - List += I.FullName(true) + "* "; - else - List += I.FullName(true) + " "; - - VersionsList += string(Cache[I].CandVersion)+ "\n"; - } - } - - ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList); -} - /*}}}*/ -// ShowKept - Show kept packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void ShowKept(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false || - I->CurrentVer == 0 || Cache[I].Delete() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - ShowList(out,_("The following packages have been kept back:"),List,VersionsList); -} - /*}}}*/ -// ShowUpgraded - Show upgraded packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void ShowUpgraded(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - ShowList(out,_("The following packages will be upgraded:"),List,VersionsList); -} - /*}}}*/ -// ShowDowngraded - Show downgraded packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool ShowDowngraded(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList); -} - /*}}}*/ -// ShowHold - Show held but changed packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool ShowHold(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() && - I->SelectedState == pkgCache::State::Hold) { - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - } - - return ShowList(out,_("The following held packages will be changed:"),List,VersionsList); -} - /*}}}*/ -// ShowEssential - Show an essential package warning /*{{{*/ -// --------------------------------------------------------------------- -/* This prints out a warning message that is not to be ignored. It shows - all essential packages and their dependents that are to be removed. - It is insanely risky to remove the dependents of an essential package! */ -bool ShowEssential(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - bool *Added = new bool[Cache->Head().PackageCount]; - for (unsigned int I = 0; I != Cache->Head().PackageCount; I++) - Added[I] = false; - - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential && - (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important) - continue; - - // The essential package is being removed - if (Cache[I].Delete() == true) - { - if (Added[I->ID] == false) - { - Added[I->ID] = true; - List += I.FullName(true) + " "; - //VersionsList += string(Cache[I].CurVersion) + "\n"; ??? - } - } - else - continue; - - if (I->CurrentVer == 0) - continue; - - // Print out any essential package depenendents that are to be removed - for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D) - { - // Skip everything but depends - if (D->Type != pkgCache::Dep::PreDepends && - D->Type != pkgCache::Dep::Depends) - continue; - - pkgCache::PkgIterator P = D.SmartTargetPkg(); - if (Cache[P].Delete() == true) - { - if (Added[P->ID] == true) - continue; - Added[P->ID] = true; - - char S[300]; - snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str()); - List += S; - //VersionsList += "\n"; ??? - } - } - } - - delete [] Added; - return ShowList(out,_("WARNING: The following essential packages will be removed.\n" - "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList); -} - - /*}}}*/ -// Stats - Show some statistics /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void Stats(ostream &out,pkgDepCache &Dep) -{ - unsigned long Upgrade = 0; - unsigned long Downgrade = 0; - unsigned long Install = 0; - unsigned long ReInstall = 0; - for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I) - { - if (Dep[I].NewInstall() == true) - Install++; - else - { - if (Dep[I].Upgrade() == true) - Upgrade++; - else - if (Dep[I].Downgrade() == true) - Downgrade++; - } - - if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall) - ReInstall++; - } - - ioprintf(out,_("%lu upgraded, %lu newly installed, "), - Upgrade,Install); - - if (ReInstall != 0) - ioprintf(out,_("%lu reinstalled, "),ReInstall); - if (Downgrade != 0) - ioprintf(out,_("%lu downgraded, "),Downgrade); - - ioprintf(out,_("%lu to remove and %lu not upgraded.\n"), - Dep.DelCount(),Dep.KeepCount()); - - if (Dep.BadCount() != 0) - ioprintf(out,_("%lu not fully installed or removed.\n"), - Dep.BadCount()); -} - /*}}}*/ -// CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/ -class CacheSetHelperAPTGet : public APT::CacheSetHelper { - /** \brief stream message should be printed to */ - std::ostream &out; - /** \brief were things like Task or RegEx used to select packages? */ - bool explicitlyNamed; - - APT::PackageSet virtualPkgs; - -public: - std::list<std::pair<pkgCache::VerIterator, std::string> > selectedByRelease; - - CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) { - explicitlyNamed = true; - } - - virtual void showTaskSelection(pkgCache::PkgIterator const &Pkg, string const &pattern) { - ioprintf(out, _("Note, selecting '%s' for task '%s'\n"), - Pkg.FullName(true).c_str(), pattern.c_str()); - explicitlyNamed = false; - } - virtual void showRegExSelection(pkgCache::PkgIterator const &Pkg, string const &pattern) { - ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"), - Pkg.FullName(true).c_str(), pattern.c_str()); - explicitlyNamed = false; - } - virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver, - string const &ver, bool const verIsRel) { - if (ver == Ver.VerStr()) - return; - selectedByRelease.push_back(make_pair(Ver, ver)); - } - - bool showVirtualPackageErrors(pkgCacheFile &Cache) { - if (virtualPkgs.empty() == true) - return true; - for (APT::PackageSet::const_iterator Pkg = virtualPkgs.begin(); - Pkg != virtualPkgs.end(); ++Pkg) { - if (Pkg->ProvidesList != 0) { - ioprintf(c1out,_("Package %s is a virtual package provided by:\n"), - Pkg.FullName(true).c_str()); - - pkgCache::PrvIterator I = Pkg.ProvidesList(); - unsigned short provider = 0; - for (; I.end() == false; ++I) { - pkgCache::PkgIterator Pkg = I.OwnerPkg(); - - if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) { - c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr(); - if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false) - c1out << _(" [Installed]"); - c1out << endl; - ++provider; - } - } - // if we found no candidate which provide this package, show non-candidates - if (provider == 0) - for (I = Pkg.ProvidesList(); I.end() == false; ++I) - c1out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr() - << _(" [Not candidate version]") << endl; - else - out << _("You should explicitly select one to install.") << endl; - } else { - ioprintf(c1out, - _("Package %s is not available, but is referred to by another package.\n" - "This may mean that the package is missing, has been obsoleted, or\n" - "is only available from another source\n"),Pkg.FullName(true).c_str()); - - string List; - string VersionsList; - SPtrArray<bool> Seen = new bool[Cache.GetPkgCache()->Head().PackageCount]; - memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen)); - for (pkgCache::DepIterator Dep = Pkg.RevDependsList(); - Dep.end() == false; ++Dep) { - if (Dep->Type != pkgCache::Dep::Replaces) - continue; - if (Seen[Dep.ParentPkg()->ID] == true) - continue; - Seen[Dep.ParentPkg()->ID] = true; - List += Dep.ParentPkg().FullName(true) + " "; - //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ??? - } - ShowList(c1out,_("However the following packages replace it:"),List,VersionsList); - } - c1out << std::endl; - } - return false; - } - - virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { - APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE); - if (verset.empty() == false) - return *(verset.begin()); - else if (ShowError == true) { - _error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str()); - virtualPkgs.insert(Pkg); - } - return pkgCache::VerIterator(Cache, 0); - } - - virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { - if (Pkg->ProvidesList != 0) - { - APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST); - if (verset.empty() == false) - return *(verset.begin()); - if (ShowError == true) - ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str()); - } - else - { - pkgCache::GrpIterator Grp = Pkg.Group(); - pkgCache::PkgIterator P = Grp.PackageList(); - for (; P.end() != true; P = Grp.NextPkg(P)) - { - if (P == Pkg) - continue; - if (P->CurrentVer != 0) { - // TRANSLATORS: Note, this is not an interactive question - ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"), - Pkg.FullName(true).c_str(), P.FullName(true).c_str()); - break; - } - } - if (P.end() == true) - ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str()); - } - return pkgCache::VerIterator(Cache, 0); - } - - APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg, - APT::VersionSet::Version const &select) { - /* This is a pure virtual package and there is a single available - candidate providing it. */ - if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0) - return APT::VersionSet(); - - pkgCache::PkgIterator Prov; - bool found_one = false; - for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) { - pkgCache::VerIterator const PVer = P.OwnerVer(); - pkgCache::PkgIterator const PPkg = PVer.ParentPkg(); - - /* Ignore versions that are not a candidate. */ - if (Cache[PPkg].CandidateVer != PVer) - continue; - - if (found_one == false) { - Prov = PPkg; - found_one = true; - } else if (PPkg != Prov) { - // same group, so it's a foreign package - if (PPkg->Group == Prov->Group) { - // do we already have the requested arch? - if (strcmp(Pkg.Arch(), Prov.Arch()) == 0 || - strcmp(Prov.Arch(), "all") == 0 || - unlikely(strcmp(PPkg.Arch(), Prov.Arch()) == 0)) // packages have only on candidate, but just to be sure - continue; - // see which architecture we prefer more and switch to it - std::vector<std::string> archs = APT::Configuration::getArchitectures(); - if (std::find(archs.begin(), archs.end(), PPkg.Arch()) < std::find(archs.begin(), archs.end(), Prov.Arch())) - Prov = PPkg; - continue; - } - found_one = false; // we found at least two - break; - } - } - - if (found_one == true) { - ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"), - Prov.FullName(true).c_str(), Pkg.FullName(true).c_str()); - return APT::VersionSet::FromPackage(Cache, Prov, select, *this); - } - return APT::VersionSet(); - } - - inline bool allPkgNamedExplicitly() const { return explicitlyNamed; } - -}; - /*}}}*/ -// TryToInstall - Mark a package for installation /*{{{*/ -struct TryToInstall { - pkgCacheFile* Cache; - pkgProblemResolver* Fix; - bool FixBroken; - unsigned long AutoMarkChanged; - APT::PackageSet doAutoInstallLater; - - TryToInstall(pkgCacheFile &Cache, pkgProblemResolver *PM, bool const FixBroken) : Cache(&Cache), Fix(PM), - FixBroken(FixBroken), AutoMarkChanged(0) {}; - - void operator() (pkgCache::VerIterator const &Ver) { - pkgCache::PkgIterator Pkg = Ver.ParentPkg(); - - Cache->GetDepCache()->SetCandidateVersion(Ver); - pkgDepCache::StateCache &State = (*Cache)[Pkg]; - - // Handle the no-upgrade case - if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0) - ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"), - Pkg.FullName(true).c_str()); - // Ignore request for install if package would be new - else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0) - ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"), - Pkg.FullName(true).c_str()); - else { - if (Fix != NULL) { - Fix->Clear(Pkg); - Fix->Protect(Pkg); - } - Cache->GetDepCache()->MarkInstall(Pkg,false); - - if (State.Install() == false) { - if (_config->FindB("APT::Get::ReInstall",false) == true) { - if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false) - ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"), - Pkg.FullName(true).c_str()); - else - Cache->GetDepCache()->SetReInstall(Pkg, true); - } else - ioprintf(c1out,_("%s is already the newest version.\n"), - Pkg.FullName(true).c_str()); - } - - // Install it with autoinstalling enabled (if we not respect the minial - // required deps or the policy) - if (FixBroken == false) - doAutoInstallLater.insert(Pkg); - } - - // see if we need to fix the auto-mark flag - // e.g. apt-get install foo - // where foo is marked automatic - if (State.Install() == false && - (State.Flags & pkgCache::Flag::Auto) && - _config->FindB("APT::Get::ReInstall",false) == false && - _config->FindB("APT::Get::Only-Upgrade",false) == false && - _config->FindB("APT::Get::Download-Only",false) == false) - { - ioprintf(c1out,_("%s set to manually installed.\n"), - Pkg.FullName(true).c_str()); - Cache->GetDepCache()->MarkAuto(Pkg,false); - AutoMarkChanged++; - } - } - - bool propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > start, std::ostream &out) - { - for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin(); - s != start.end(); ++s) - Cache->GetDepCache()->SetCandidateVersion(s->first); - - bool Success = true; - std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed; - for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin(); - s != start.end(); ++s) - { - Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache))); - // We continue here even if it failed to enhance the ShowBroken output - Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed); - } - for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin(); - c != Changed.end(); ++c) - { - if (c->second.end() == true) - ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"), - c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str()); - else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group) - { - pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache); - ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(), - V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str()); - } - } - return Success; - } - - void doAutoInstall() { - for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin(); - P != doAutoInstallLater.end(); ++P) { - pkgDepCache::StateCache &State = (*Cache)[P]; - if (State.InstBroken() == false && State.InstPolicyBroken() == false) - continue; - Cache->GetDepCache()->MarkInstall(P, true); - } - doAutoInstallLater.clear(); - } -}; - /*}}}*/ -// TryToRemove - Mark a package for removal /*{{{*/ -struct TryToRemove { - pkgCacheFile* Cache; - pkgProblemResolver* Fix; - bool PurgePkgs; - - TryToRemove(pkgCacheFile &Cache, pkgProblemResolver *PM) : Cache(&Cache), Fix(PM), - PurgePkgs(_config->FindB("APT::Get::Purge", false)) {}; - - void operator() (pkgCache::VerIterator const &Ver) - { - pkgCache::PkgIterator Pkg = Ver.ParentPkg(); - - if (Fix != NULL) - { - Fix->Clear(Pkg); - Fix->Protect(Pkg); - Fix->Remove(Pkg); - } - - if ((Pkg->CurrentVer == 0 && PurgePkgs == false) || - (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled)) - { - pkgCache::GrpIterator Grp = Pkg.Group(); - pkgCache::PkgIterator P = Grp.PackageList(); - for (; P.end() != true; P = Grp.NextPkg(P)) - { - if (P == Pkg) - continue; - if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled)) - { - // TRANSLATORS: Note, this is not an interactive question - ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"), - Pkg.FullName(true).c_str(), P.FullName(true).c_str()); - break; - } - } - if (P.end() == true) - ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str()); - - // MarkInstall refuses to install packages on hold - Pkg->SelectedState = pkgCache::State::Hold; - } - else - Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs); - } -}; - /*}}}*/ -// CacheFile::NameComp - QSort compare by name /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache *CacheFile::SortCache = 0; -int CacheFile::NameComp(const void *a,const void *b) -{ - if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0) - return *(pkgCache::Package **)a - *(pkgCache::Package **)b; - - const pkgCache::Package &A = **(pkgCache::Package **)a; - const pkgCache::Package &B = **(pkgCache::Package **)b; - - return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name); -} - /*}}}*/ -// CacheFile::Sort - Sort by name /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void CacheFile::Sort() -{ - delete [] List; - List = new pkgCache::Package *[Cache->Head().PackageCount]; - memset(List,0,sizeof(*List)*Cache->Head().PackageCount); - pkgCache::PkgIterator I = Cache->PkgBegin(); - for (;I.end() != true; ++I) - List[I->ID] = I; - - SortCache = *this; - qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp); -} - /*}}}*/ -// CacheFile::CheckDeps - Open the cache file /*{{{*/ -// --------------------------------------------------------------------- -/* This routine generates the caches and then opens the dependency cache - and verifies that the system is OK. */ -bool CacheFile::CheckDeps(bool AllowBroken) -{ - bool FixBroken = _config->FindB("APT::Get::Fix-Broken",false); - - if (_error->PendingError() == true) - return false; - - // Check that the system is OK - if (DCache->DelCount() != 0 || DCache->InstCount() != 0) - return _error->Error("Internal error, non-zero counts"); - - // Apply corrections for half-installed packages - if (pkgApplyStatus(*DCache) == false) - return false; - - if (_config->FindB("APT::Get::Fix-Policy-Broken",false) == true) - { - FixBroken = true; - if ((DCache->PolicyBrokenCount() > 0)) - { - // upgrade all policy-broken packages with ForceImportantDeps=True - for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); ++I) - if ((*DCache)[I].NowPolicyBroken() == true) - DCache->MarkInstall(I,true,0, false, true); - } - } - - // Nothing is broken - if (DCache->BrokenCount() == 0 || AllowBroken == true) - return true; - - // Attempt to fix broken things - if (FixBroken == true) - { - c1out << _("Correcting dependencies...") << flush; - if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0) - { - c1out << _(" failed.") << endl; - ShowBroken(c1out,*this,true); - - return _error->Error(_("Unable to correct dependencies")); - } - if (pkgMinimizeUpgrade(*DCache) == false) - return _error->Error(_("Unable to minimize the upgrade set")); - - c1out << _(" Done") << endl; - } - else - { - c1out << _("You might want to run 'apt-get -f install' to correct these.") << endl; - ShowBroken(c1out,*this,true); - - return _error->Error(_("Unmet dependencies. Try using -f.")); - } - - return true; -} - /*}}}*/ -// CheckAuth - check if each download comes form a trusted source /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static bool CheckAuth(pkgAcquire& Fetcher) -{ - string UntrustedList; - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I) - { - if (!(*I)->IsTrusted()) - { - UntrustedList += string((*I)->ShortDesc()) + " "; - } - } - - if (UntrustedList == "") - { - return true; - } - - ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,""); - - if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true) - { - c2out << _("Authentication warning overridden.\n"); - return true; - } - - if (_config->FindI("quiet",0) < 2 - && _config->FindB("APT::Get::Assume-Yes",false) == false) - { - c2out << _("Install these packages without verification?") << flush; - if (!YnPrompt(false)) - return _error->Error(_("Some packages could not be authenticated")); - - return true; - } - else if (_config->FindB("APT::Get::Force-Yes",false) == true) - { - return true; - } - - return _error->Error(_("There are problems and -y was used without --force-yes")); -} - /*}}}*/ -// InstallPackages - Actually download and install the packages /*{{{*/ -// --------------------------------------------------------------------- -/* This displays the informative messages describing what is going to - happen and then calls the download routines */ -bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, - bool Safety = true) -{ - if (_config->FindB("APT::Get::Purge",false) == true) - { - pkgCache::PkgIterator I = Cache->PkgBegin(); - for (; I.end() == false; ++I) - { - if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete) - Cache->MarkDelete(I,true); - } - } - - bool Fail = false; - bool Essential = false; - - // Show all the various warning indicators - ShowDel(c1out,Cache); - ShowNew(c1out,Cache); - if (ShwKept == true) - ShowKept(c1out,Cache); - Fail |= !ShowHold(c1out,Cache); - if (_config->FindB("APT::Get::Show-Upgraded",true) == true) - ShowUpgraded(c1out,Cache); - Fail |= !ShowDowngraded(c1out,Cache); - if (_config->FindB("APT::Get::Download-Only",false) == false) - Essential = !ShowEssential(c1out,Cache); - Fail |= Essential; - Stats(c1out,Cache); - - // Sanity check - if (Cache->BrokenCount() != 0) - { - ShowBroken(c1out,Cache,false); - return _error->Error(_("Internal error, InstallPackages was called with broken packages!")); - } - - if (Cache->DelCount() == 0 && Cache->InstCount() == 0 && - Cache->BadCount() == 0) - return true; - - // No remove flag - if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false) - return _error->Error(_("Packages need to be removed but remove is disabled.")); - - // Run the simulator .. - if (_config->FindB("APT::Get::Simulate") == true) - { - pkgSimulate PM(Cache); - int status_fd = _config->FindI("APT::Status-Fd",-1); - pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd); - if (Res == pkgPackageManager::Failed) - return false; - if (Res != pkgPackageManager::Completed) - return _error->Error(_("Internal error, Ordering didn't finish")); - return true; - } - - // Create the text record parser - pkgRecords Recs(Cache); - if (_error->PendingError() == true) - return false; - - // Create the download object - pkgAcquire Fetcher; - AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - if (_config->FindB("APT::Get::Print-URIs", false) == true) - { - // force a hashsum for compatibility reasons - _config->CndSet("Acquire::ForceHash", "md5sum"); - } - else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false) - return false; - // Read the source list - if (Cache.BuildSourceList() == false) - return false; - pkgSourceList *List = Cache.GetSourceList(); - - // Create the package manager and prepare to download - SPtr<pkgPackageManager> PM= _system->CreatePM(Cache); - if (PM->GetArchives(&Fetcher,List,&Recs) == false || - _error->PendingError() == true) - return false; - // Display statistics - unsigned long long FetchBytes = Fetcher.FetchNeeded(); - unsigned long long FetchPBytes = Fetcher.PartialPresent(); - unsigned long long DebBytes = Fetcher.TotalNeeded(); - if (DebBytes != Cache->DebSize()) - { - c0out << DebBytes << ',' << Cache->DebSize() << endl; - c0out << _("How odd.. The sizes didn't match, email apt@packages.debian.org") << endl; - } - - // Number of bytes - if (DebBytes != FetchBytes) - //TRANSLATOR: The required space between number and unit is already included - // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB - ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"), - SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str()); - else if (DebBytes != 0) - //TRANSLATOR: The required space between number and unit is already included - // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB - ioprintf(c1out,_("Need to get %sB of archives.\n"), - SizeToStr(DebBytes).c_str()); - - // Size delta - if (Cache->UsrSize() >= 0) - //TRANSLATOR: The required space between number and unit is already included - // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB - ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"), - SizeToStr(Cache->UsrSize()).c_str()); - else - //TRANSLATOR: The required space between number and unit is already included - // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB - ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"), - SizeToStr(-1*Cache->UsrSize()).c_str()); - - if (_error->PendingError() == true) - return false; - - /* Check for enough free space, but only if we are actually going to - download */ - if (_config->FindB("APT::Get::Print-URIs") == false && - _config->FindB("APT::Get::Download",true) == true) - { - struct statvfs Buf; - string OutputDir = _config->FindDir("Dir::Cache::Archives"); - if (statvfs(OutputDir.c_str(),&Buf) != 0) { - if (errno == EOVERFLOW) - return _error->WarningE("statvfs",_("Couldn't determine free space in %s"), - OutputDir.c_str()); - else - return _error->Errno("statvfs",_("Couldn't determine free space in %s"), - OutputDir.c_str()); - } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize) - { - struct statfs Stat; - if (statfs(OutputDir.c_str(),&Stat) != 0 -#if HAVE_STRUCT_STATFS_F_TYPE - || unsigned(Stat.f_type) != RAMFS_MAGIC -#endif - ) - return _error->Error(_("You don't have enough free space in %s."), - OutputDir.c_str()); - } - } - - // Fail safe check - if (_config->FindI("quiet",0) >= 2 || - _config->FindB("APT::Get::Assume-Yes",false) == true) - { - if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) - return _error->Error(_("There are problems and -y was used without --force-yes")); - } - - if (Essential == true && Safety == true) - { - if (_config->FindB("APT::Get::Trivial-Only",false) == true) - return _error->Error(_("Trivial Only specified but this is not a trivial operation.")); - - // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be - // careful with hard to type or special characters (like non-breaking spaces) - const char *Prompt = _("Yes, do as I say!"); - ioprintf(c2out, - _("You are about to do something potentially harmful.\n" - "To continue type in the phrase '%s'\n" - " ?] "),Prompt); - c2out << flush; - if (AnalPrompt(Prompt) == false) - { - c2out << _("Abort.") << endl; - exit(1); - } - } - else - { - // Prompt to continue - if (Ask == true || Fail == true) - { - if (_config->FindB("APT::Get::Trivial-Only",false) == true) - return _error->Error(_("Trivial Only specified but this is not a trivial operation.")); - - if (_config->FindI("quiet",0) < 2 && - _config->FindB("APT::Get::Assume-Yes",false) == false) - { - c2out << _("Do you want to continue?") << flush; - - if (YnPrompt() == false) - { - c2out << _("Abort.") << endl; - exit(1); - } - } - } - } - - // Just print out the uris an exit if the --print-uris flag was used - if (_config->FindB("APT::Get::Print-URIs") == true) - { - pkgAcquire::UriIterator I = Fetcher.UriBegin(); - for (; I != Fetcher.UriEnd(); ++I) - cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << - I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl; - return true; - } - - if (!CheckAuth(Fetcher)) - return false; - - /* Unlock the dpkg lock if we are not going to be doing an install - after. */ - if (_config->FindB("APT::Get::Download-Only",false) == true) - _system->UnLock(); - - // Run it - while (1) - { - bool Transient = false; - if (_config->FindB("APT::Get::Download",true) == false) - { - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();) - { - if ((*I)->Local == true) - { - ++I; - continue; - } - - // Close the item and check if it was found in cache - (*I)->Finished(); - if ((*I)->Complete == false) - Transient = true; - - // Clear it out of the fetch list - delete *I; - I = Fetcher.ItemsBegin(); - } - } - - if (Fetcher.Run() == pkgAcquire::Failed) - return false; - - // Print out errors - bool Failed = false; - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) - { - if ((*I)->Status == pkgAcquire::Item::StatDone && - (*I)->Complete == true) - continue; - - if ((*I)->Status == pkgAcquire::Item::StatIdle) - { - Transient = true; - // Failed = true; - continue; - } - - fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(), - (*I)->ErrorText.c_str()); - Failed = true; - } - - /* If we are in no download mode and missing files and there were - 'failures' then the user must specify -m. Furthermore, there - is no such thing as a transient error in no-download mode! */ - if (Transient == true && - _config->FindB("APT::Get::Download",true) == false) - { - Transient = false; - Failed = true; - } - - if (_config->FindB("APT::Get::Download-Only",false) == true) - { - if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false) - return _error->Error(_("Some files failed to download")); - c1out << _("Download complete and in download only mode") << endl; - return true; - } - - if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false) - { - return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?")); - } - - if (Transient == true && Failed == true) - return _error->Error(_("--fix-missing and media swapping is not currently supported")); - - // Try to deal with missing package files - if (Failed == true && PM->FixMissing() == false) - { - cerr << _("Unable to correct missing packages.") << endl; - return _error->Error(_("Aborting install.")); - } - - _system->UnLock(); - int status_fd = _config->FindI("APT::Status-Fd",-1); - pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd); - if (Res == pkgPackageManager::Failed || _error->PendingError() == true) - return false; - if (Res == pkgPackageManager::Completed) - break; - - // Reload the fetcher object and loop again for media swapping - Fetcher.Shutdown(); - if (PM->GetArchives(&Fetcher,List,&Recs) == false) - return false; - - _system->Lock(); - } - - std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages(); - if (disappearedPkgs.empty() == true) - return true; - - string disappear; - for (std::set<std::string>::const_iterator d = disappearedPkgs.begin(); - d != disappearedPkgs.end(); ++d) - disappear.append(*d).append(" "); - - ShowList(c1out, P_("The following package disappeared from your system as\n" - "all files have been overwritten by other packages:", - "The following packages disappeared from your system as\n" - "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, ""); - c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl; - - return true; -} - /*}}}*/ // TryToInstallBuildDep - Try to install a single package /*{{{*/ // --------------------------------------------------------------------- /* This used to be inlined in DoInstall, but with the advent of regex package @@ -1667,497 +302,6 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, return Last; } /*}}}*/ -// DoUpdate - Update the package lists /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool DoUpdate(CommandLine &CmdL) -{ - if (CmdL.FileSize() != 1) - return _error->Error(_("The update command takes no arguments")); - - CacheFile Cache; - - // Get the source list - if (Cache.BuildSourceList() == false) - return false; - pkgSourceList *List = Cache.GetSourceList(); - - // Create the progress - AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - - // Just print out the uris an exit if the --print-uris flag was used - if (_config->FindB("APT::Get::Print-URIs") == true) - { - // force a hashsum for compatibility reasons - _config->CndSet("Acquire::ForceHash", "md5sum"); - - // get a fetcher - pkgAcquire Fetcher; - if (Fetcher.Setup(&Stat) == false) - return false; - - // Populate it with the source selection and get all Indexes - // (GetAll=true) - if (List->GetIndexes(&Fetcher,true) == false) - return false; - - pkgAcquire::UriIterator I = Fetcher.UriBegin(); - for (; I != Fetcher.UriEnd(); ++I) - cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << - I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl; - return true; - } - - // do the work - if (_config->FindB("APT::Get::Download",true) == true) - ListUpdate(Stat, *List); - - // Rebuild the cache. - if (_config->FindB("pkgCacheFile::Generate", true) == true) - { - pkgCacheFile::RemoveCaches(); - if (Cache.BuildCaches() == false) - return false; - } - - return true; -} - /*}}}*/ -// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/ -// --------------------------------------------------------------------- -/* Remove unused automatic packages */ -bool DoAutomaticRemove(CacheFile &Cache) -{ - bool Debug = _config->FindI("Debug::pkgAutoRemove",false); - bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false); - bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove"); - - pkgDepCache::ActionGroup group(*Cache); - if(Debug) - std::cout << "DoAutomaticRemove()" << std::endl; - - if (doAutoRemove == true && - _config->FindB("APT::Get::Remove",true) == false) - { - c1out << _("We are not supposed to delete stuff, can't start " - "AutoRemover") << std::endl; - return false; - } - - bool purgePkgs = _config->FindB("APT::Get::Purge", false); - bool smallList = (hideAutoRemove == false && - strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0); - - unsigned long autoRemoveCount = 0; - APT::PackageSet tooMuch; - APT::PackageList autoRemoveList; - // look over the cache to see what can be removed - for (unsigned J = 0; J < Cache->Head().PackageCount; ++J) - { - pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); - if (Cache[Pkg].Garbage) - { - if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install()) - if(Debug) - std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl; - - if (doAutoRemove) - { - if(Pkg.CurrentVer() != 0 && - Pkg->CurrentState != pkgCache::State::ConfigFiles) - Cache->MarkDelete(Pkg, purgePkgs, 0, false); - else - Cache->MarkKeep(Pkg, false, false); - } - else - { - if (hideAutoRemove == false && Cache[Pkg].Delete() == false) - autoRemoveList.insert(Pkg); - // if the package is a new install and already garbage we don't need to - // install it in the first place, so nuke it instead of show it - if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0) - { - if (Pkg.CandVersion() != 0) - tooMuch.insert(Pkg); - Cache->MarkDelete(Pkg, false, 0, false); - } - // only show stuff in the list that is not yet marked for removal - else if(hideAutoRemove == false && Cache[Pkg].Delete() == false) - ++autoRemoveCount; - } - } - } - - // we could have removed a new dependency of a garbage package, - // so check if a reverse depends is broken and if so install it again. - if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0)) - { - bool Changed; - do { - Changed = false; - for (APT::PackageSet::const_iterator Pkg = tooMuch.begin(); - Pkg != tooMuch.end() && Changed == false; ++Pkg) - { - APT::PackageSet too; - too.insert(*Pkg); - for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList(); - Prv.end() == false; ++Prv) - too.insert(Prv.ParentPkg()); - for (APT::PackageSet::const_iterator P = too.begin(); - P != too.end() && Changed == false; ++P) { - for (pkgCache::DepIterator R = P.RevDependsList(); - R.end() == false; ++R) - { - if (R.IsNegative() == true || - Cache->IsImportantDep(R) == false) - continue; - pkgCache::PkgIterator N = R.ParentPkg(); - if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false)) - continue; - if (Debug == true) - std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl; - Cache->MarkInstall(Pkg, false, 0, false); - if (hideAutoRemove == false) - ++autoRemoveCount; - tooMuch.erase(Pkg); - Changed = true; - break; - } - } - } - } while (Changed == true); - } - - std::string autoremovelist, autoremoveversions; - if (smallList == false && autoRemoveCount != 0) - { - for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg) - { - if (Cache[Pkg].Garbage == false) - continue; - autoremovelist += Pkg.FullName(true) + " "; - autoremoveversions += string(Cache[Pkg].CandVersion) + "\n"; - } - } - - // Now see if we had destroyed anything (if we had done anything) - if (Cache->BrokenCount() != 0) - { - c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n" - "shouldn't happen. Please file a bug report against apt.") << endl; - c1out << endl; - c1out << _("The following information may help to resolve the situation:") << endl; - c1out << endl; - ShowBroken(c1out,Cache,false); - - return _error->Error(_("Internal Error, AutoRemover broke stuff")); - } - - // if we don't remove them, we should show them! - if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0)) - { - if (smallList == false) - ShowList(c1out, P_("The following package was automatically installed and is no longer required:", - "The following packages were automatically installed and are no longer required:", - autoRemoveCount), autoremovelist, autoremoveversions); - else - ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n", - "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount); - c1out << P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount) << std::endl; - } - return true; -} - /*}}}*/ -// DoUpgrade - Upgrade all packages /*{{{*/ -// --------------------------------------------------------------------- -/* Upgrade all packages without installing new packages or erasing old - packages */ -bool DoUpgrade(CommandLine &CmdL) -{ - CacheFile Cache; - if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) - return false; - - // Do the upgrade - if (pkgAllUpgrade(Cache) == false) - { - ShowBroken(c1out,Cache,false); - return _error->Error(_("Internal error, AllUpgrade broke stuff")); - } - - return InstallPackages(Cache,true); -} - /*}}}*/ -// DoInstall - Install packages from the command line /*{{{*/ -// --------------------------------------------------------------------- -/* Install named packages */ -bool DoInstall(CommandLine &CmdL) -{ - CacheFile Cache; - if (Cache.OpenForInstall() == false || - Cache.CheckDeps(CmdL.FileSize() != 1) == false) - return false; - - // Enter the special broken fixing mode if the user specified arguments - bool BrokenFix = false; - if (Cache->BrokenCount() != 0) - BrokenFix = true; - - pkgProblemResolver* Fix = NULL; - if (_config->FindB("APT::Get::CallResolver", true) == true) - Fix = new pkgProblemResolver(Cache); - - static const unsigned short MOD_REMOVE = 1; - static const unsigned short MOD_INSTALL = 2; - - unsigned short fallback = MOD_INSTALL; - if (strcasecmp(CmdL.FileList[0],"remove") == 0) - fallback = MOD_REMOVE; - else if (strcasecmp(CmdL.FileList[0], "purge") == 0) - { - _config->Set("APT::Get::Purge", true); - fallback = MOD_REMOVE; - } - else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0) - { - _config->Set("APT::Get::AutomaticRemove", "true"); - fallback = MOD_REMOVE; - } - - std::list<APT::VersionSet::Modifier> mods; - mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+", - APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE)); - mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-", - APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST)); - CacheSetHelperAPTGet helper(c0out); - std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache, - CmdL.FileList + 1, mods, fallback, helper); - - if (_error->PendingError() == true) - { - helper.showVirtualPackageErrors(Cache); - if (Fix != NULL) - delete Fix; - return false; - } - - - TryToInstall InstallAction(Cache, Fix, BrokenFix); - TryToRemove RemoveAction(Cache, Fix); - - // new scope for the ActionGroup - { - pkgDepCache::ActionGroup group(Cache); - unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 }; - - for (unsigned short i = 0; order[i] != 0; ++i) - { - if (order[i] == MOD_INSTALL) - InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction); - else if (order[i] == MOD_REMOVE) - RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction); - } - - if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true) - { - for (unsigned short i = 0; order[i] != 0; ++i) - { - if (order[i] != MOD_INSTALL) - continue; - InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out); - InstallAction.doAutoInstall(); - } - } - - if (_error->PendingError() == true) - { - if (Fix != NULL) - delete Fix; - return false; - } - - /* If we are in the Broken fixing mode we do not attempt to fix the - problems. This is if the user invoked install without -f and gave - packages */ - if (BrokenFix == true && Cache->BrokenCount() != 0) - { - c1out << _("You might want to run 'apt-get -f install' to correct these:") << endl; - ShowBroken(c1out,Cache,false); - if (Fix != NULL) - delete Fix; - return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).")); - } - - if (Fix != NULL) - { - // Call the scored problem resolver - Fix->Resolve(true); - delete Fix; - } - - // Now we check the state of the packages, - if (Cache->BrokenCount() != 0) - { - c1out << - _("Some packages could not be installed. This may mean that you have\n" - "requested an impossible situation or if you are using the unstable\n" - "distribution that some required packages have not yet been created\n" - "or been moved out of Incoming.") << endl; - /* - if (Packages == 1) - { - c1out << endl; - c1out << - _("Since you only requested a single operation it is extremely likely that\n" - "the package is simply not installable and a bug report against\n" - "that package should be filed.") << endl; - } - */ - - c1out << _("The following information may help to resolve the situation:") << endl; - c1out << endl; - ShowBroken(c1out,Cache,false); - if (_error->PendingError() == true) - return false; - else - return _error->Error(_("Broken packages")); - } - } - if (!DoAutomaticRemove(Cache)) - return false; - - /* Print out a list of packages that are going to be installed extra - to what the user asked */ - if (Cache->InstCount() != verset[MOD_INSTALL].size()) - { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if ((*Cache)[I].Install() == false) - continue; - pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache); - - if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end()) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CandVersion) + "\n"; - } - - ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList); - } - - /* Print out a list of suggested and recommended packages */ - { - string SuggestsList, RecommendsList; - string SuggestsVersions, RecommendsVersions; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); - - /* Just look at the ones we want to install */ - if ((*Cache)[Pkg].Install() == false) - continue; - - // get the recommends/suggests for the candidate ver - pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache); - for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; ) - { - pkgCache::DepIterator Start; - pkgCache::DepIterator End; - D.GlobOr(Start,End); // advances D - - // FIXME: we really should display a or-group as a or-group to the user - // the problem is that ShowList is incapable of doing this - string RecommendsOrList,RecommendsOrVersions; - string SuggestsOrList,SuggestsOrVersions; - bool foundInstalledInOrGroup = false; - for(;;) - { - /* Skip if package is installed already, or is about to be */ - string target = Start.TargetPkg().FullName(true) + " "; - pkgCache::PkgIterator const TarPkg = Start.TargetPkg(); - if (TarPkg->SelectedState == pkgCache::State::Install || - TarPkg->SelectedState == pkgCache::State::Hold || - Cache[Start.TargetPkg()].Install()) - { - foundInstalledInOrGroup=true; - break; - } - - /* Skip if we already saw it */ - if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1) - { - foundInstalledInOrGroup=true; - break; - } - - // this is a dep on a virtual pkg, check if any package that provides it - // should be installed - if(Start.TargetPkg().ProvidesList() != 0) - { - pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList(); - for (; I.end() == false; ++I) - { - pkgCache::PkgIterator Pkg = I.OwnerPkg(); - if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() && - Pkg.CurrentVer() != 0) - foundInstalledInOrGroup=true; - } - } - - if (Start->Type == pkgCache::Dep::Suggests) - { - SuggestsOrList += target; - SuggestsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n"; - } - - if (Start->Type == pkgCache::Dep::Recommends) - { - RecommendsOrList += target; - RecommendsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n"; - } - - if (Start >= End) - break; - ++Start; - } - - if(foundInstalledInOrGroup == false) - { - RecommendsList += RecommendsOrList; - RecommendsVersions += RecommendsOrVersions; - SuggestsList += SuggestsOrList; - SuggestsVersions += SuggestsOrVersions; - } - - } - } - - ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions); - ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions); - - } - - // if nothing changed in the cache, but only the automark information - // we write the StateFile here, otherwise it will be written in - // cache.commit() - if (InstallAction.AutoMarkChanged > 0 && - Cache->DelCount() == 0 && Cache->InstCount() == 0 && - Cache->BadCount() == 0 && - _config->FindB("APT::Get::Simulate",false) == false) - Cache->writeStateFile(NULL); - - // See if we need to prompt - // FIXME: check if really the packages in the set are going to be installed - if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0) - return InstallPackages(Cache,false,false); - - return InstallPackages(Cache,false); -} - /*}}}*/ /* mark packages as automatically/manually installed. {{{*/ bool DoMarkAuto(CommandLine &CmdL) { @@ -2585,7 +729,7 @@ bool DoSource(CommandLine &CmdL) if(queued.find(Last->Index().ArchiveURI(I->Path)) != queued.end()) continue; queued.insert(Last->Index().ArchiveURI(I->Path)); - + // check if we have a file with that md5 sum already localy if(!I->MD5Hash.empty() && FileExists(flNotDir(I->Path))) { @@ -3367,23 +1511,6 @@ bool DoChangelog(CommandLine &CmdL) return true; } /*}}}*/ -// DoMoo - Never Ask, Never Tell /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool DoMoo(CommandLine &CmdL) -{ - cout << - " (__) \n" - " (oo) \n" - " /------\\/ \n" - " / | || \n" - " * /\\---/\\ \n" - " ~~ ~~ \n" - "....\"Have you mooed today?\"...\n"; - - return true; -} - /*}}}*/ // ShowHelp - Show a help screen /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -3494,58 +1621,17 @@ void SigWinch(int) #endif } /*}}}*/ + +bool DoUpgrade(CommandLine &CmdL) +{ + if (_config->FindB("APT::Get::UpgradeAllowNew", false) == true) + return DoUpgradeWithAllowNewPackages(CmdL); + else + return DoUpgradeNoNewPackages(CmdL); +} + int main(int argc,const char *argv[]) /*{{{*/ { - CommandLine::Args Args[] = { - {'h',"help","help",0}, - {'v',"version","version",0}, - {'V',"verbose-versions","APT::Get::Show-Versions",0}, - {'q',"quiet","quiet",CommandLine::IntLevel}, - {'q',"silent","quiet",CommandLine::IntLevel}, - {'d',"download-only","APT::Get::Download-Only",0}, - {'b',"compile","APT::Get::Compile",0}, - {'b',"build","APT::Get::Compile",0}, - {'s',"simulate","APT::Get::Simulate",0}, - {'s',"just-print","APT::Get::Simulate",0}, - {'s',"recon","APT::Get::Simulate",0}, - {'s',"dry-run","APT::Get::Simulate",0}, - {'s',"no-act","APT::Get::Simulate",0}, - {'y',"yes","APT::Get::Assume-Yes",0}, - {'y',"assume-yes","APT::Get::Assume-Yes",0}, - {0,"assume-no","APT::Get::Assume-No",0}, - {'f',"fix-broken","APT::Get::Fix-Broken",0}, - {'u',"show-upgraded","APT::Get::Show-Upgraded",0}, - {'m',"ignore-missing","APT::Get::Fix-Missing",0}, - {'t',"target-release","APT::Default-Release",CommandLine::HasArg}, - {'t',"default-release","APT::Default-Release",CommandLine::HasArg}, - {'a',"host-architecture","APT::Get::Host-Architecture",CommandLine::HasArg}, - {0,"download","APT::Get::Download",0}, - {0,"fix-missing","APT::Get::Fix-Missing",0}, - {0,"ignore-hold","APT::Ignore-Hold",0}, - {0,"upgrade","APT::Get::upgrade",0}, - {0,"only-upgrade","APT::Get::Only-Upgrade",0}, - {0,"force-yes","APT::Get::force-yes",0}, - {0,"print-uris","APT::Get::Print-URIs",0}, - {0,"diff-only","APT::Get::Diff-Only",0}, - {0,"debian-only","APT::Get::Diff-Only",0}, - {0,"tar-only","APT::Get::Tar-Only",0}, - {0,"dsc-only","APT::Get::Dsc-Only",0}, - {0,"purge","APT::Get::Purge",0}, - {0,"list-cleanup","APT::Get::List-Cleanup",0}, - {0,"reinstall","APT::Get::ReInstall",0}, - {0,"trivial-only","APT::Get::Trivial-Only",0}, - {0,"remove","APT::Get::Remove",0}, - {0,"only-source","APT::Get::Only-Source",0}, - {0,"arch-only","APT::Get::Arch-Only",0}, - {0,"auto-remove","APT::Get::AutomaticRemove",0}, - {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0}, - {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean}, - {0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean}, - {0,"fix-policy","APT::Get::Fix-Policy-Broken",0}, - {0,"solver","APT::Solver",CommandLine::HasArg}, - {'c',"config-file",0,CommandLine::ConfigFile}, - {'o',"option",0,CommandLine::ArbItem}, - {0,0,0,0}}; CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate}, {"upgrade",&DoUpgrade}, {"install",&DoInstall}, @@ -3567,12 +1653,14 @@ int main(int argc,const char *argv[]) /*{{{*/ {"help",&ShowHelp}, {0,0}}; + std::vector<CommandLine::Args> Args = getCommandArgs("apt-get", CommandLine::GetCommand(Cmds, argc, argv)); + // Set up gettext support setlocale(LC_ALL,""); textdomain(PACKAGE); // Parse the command line and initialize the package library - CommandLine CmdL(Args,_config); + CommandLine CmdL(Args.data(),_config); if (pkgInitConfig(*_config) == false || CmdL.Parse(argc,argv) == false || pkgInitSystem(*_config,_system) == false) @@ -3593,33 +1681,15 @@ int main(int argc,const char *argv[]) /*{{{*/ return 0; } - // simulate user-friendly if apt-get has no root privileges - if (getuid() != 0 && _config->FindB("APT::Get::Simulate") == true && - (CmdL.FileSize() == 0 || - (strcmp(CmdL.FileList[0], "source") != 0 && strcmp(CmdL.FileList[0], "download") != 0 && - strcmp(CmdL.FileList[0], "changelog") != 0))) - { - if (_config->FindB("APT::Get::Show-User-Simulation-Note",true) == true) - cout << _("NOTE: This is only a simulation!\n" - " apt-get needs root privileges for real execution.\n" - " Keep also in mind that locking is deactivated,\n" - " so don't depend on the relevance to the real current situation!" - ) << std::endl; - _config->Set("Debug::NoLocking",true); - } + // see if we are in simulate mode + CheckSimulateMode(CmdL); // Deal with stdout not being a tty if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) _config->Set("quiet","1"); // Setup the output streams - c0out.rdbuf(cout.rdbuf()); - c1out.rdbuf(cout.rdbuf()); - c2out.rdbuf(cout.rdbuf()); - if (_config->FindI("quiet",0) > 0) - c0out.rdbuf(devnull.rdbuf()); - if (_config->FindI("quiet",0) > 1) - c1out.rdbuf(devnull.rdbuf()); + InitOutput(); // Setup the signals signal(SIGPIPE,SIG_IGN); diff --git a/cmdline/apt-mark.cc b/cmdline/apt-mark.cc index 4c0fc2893..eb3410be1 100644 --- a/cmdline/apt-mark.cc +++ b/cmdline/apt-mark.cc @@ -24,6 +24,8 @@ #include <sys/wait.h> #include <fcntl.h> +#include <apt-private/private-cmndline.h> + #include <apti18n.h> /*}}}*/ using namespace std; @@ -400,21 +402,6 @@ bool ShowHelp(CommandLine &CmdL) /*}}}*/ int main(int argc,const char *argv[]) /*{{{*/ { - CommandLine::Args Args[] = { - {'h',"help","help",0}, - {0,"version","version",0}, - {'q',"quiet","quiet",CommandLine::IntLevel}, - {'q',"silent","quiet",CommandLine::IntLevel}, - {'v',"verbose","APT::MarkAuto::Verbose",0}, - {'s',"simulate","APT::Mark::Simulate",0}, - {'s',"just-print","APT::Mark::Simulate",0}, - {'s',"recon","APT::Mark::Simulate",0}, - {'s',"dry-run","APT::Mark::Simulate",0}, - {'s',"no-act","APT::Mark::Simulate",0}, - {'f',"file","Dir::State::extended_states",CommandLine::HasArg}, - {'c',"config-file",0,CommandLine::ConfigFile}, - {'o',"option",0,CommandLine::ArbItem}, - {0,0,0,0}}; CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp}, {"auto",&DoAuto}, {"manual",&DoAuto}, @@ -432,12 +419,14 @@ int main(int argc,const char *argv[]) /*{{{*/ {"unmarkauto", &DoMarkAuto}, {0,0}}; + std::vector<CommandLine::Args> Args = getCommandArgs("apt-mark", CommandLine::GetCommand(Cmds, argc, argv)); + // Set up gettext support setlocale(LC_ALL,""); textdomain(PACKAGE); // Parse the command line and initialize the package library - CommandLine CmdL(Args,_config); + CommandLine CmdL(Args.data(),_config); if (pkgInitConfig(*_config) == false || CmdL.Parse(argc,argv) == false || pkgInitSystem(*_config,_system) == false) diff --git a/cmdline/apt.cc b/cmdline/apt.cc new file mode 100644 index 000000000..e30967ec2 --- /dev/null +++ b/cmdline/apt.cc @@ -0,0 +1,158 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + apt - CLI UI for apt + + Returns 100 on failure, 0 on success. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include<config.h> + +#include <cassert> +#include <locale.h> +#include <iostream> +#include <unistd.h> +#include <errno.h> +#include <regex.h> +#include <stdio.h> +#include <iomanip> +#include <algorithm> + + +#include <apt-pkg/error.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/cacheset.h> +#include <apt-pkg/init.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/pkgrecords.h> +#include <apt-pkg/srcrecords.h> +#include <apt-pkg/version.h> +#include <apt-pkg/policy.h> +#include <apt-pkg/tagfile.h> +#include <apt-pkg/algorithms.h> +#include <apt-pkg/sptr.h> +#include <apt-pkg/pkgsystem.h> +#include <apt-pkg/indexfile.h> +#include <apt-pkg/metaindex.h> + +#include <apti18n.h> + +#include <apt-private/private-list.h> +#include <apt-private/private-search.h> +#include <apt-private/private-install.h> +#include <apt-private/private-output.h> +#include <apt-private/private-update.h> +#include <apt-private/private-cmndline.h> +#include <apt-private/private-moo.h> +#include <apt-private/private-upgrade.h> +#include <apt-private/private-show.h> +#include <apt-private/private-main.h> + /*}}}*/ + +bool ShowHelp(CommandLine &CmdL) +{ + ioprintf(c1out,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION, + COMMON_ARCH,__DATE__,__TIME__); + + // FIXME: generate from CommandLine + c1out << + _("Usage: apt [options] command\n" + "\n" + "CLI for apt.\n" + "Commands: \n" + " list - list packages based on package names\n" + " search - search in package descriptions\n" + " show - show package details\n" + "\n" + " update - update list of available packages\n" + " install - install packages\n" + " upgrade - upgrade the systems packages\n" + ); + + return true; +} + +int main(int argc, const char *argv[]) /*{{{*/ +{ + CommandLine::Dispatch Cmds[] = {{"list",&List}, + {"search", &FullTextSearch}, + {"show", &APT::Cmd::ShowPackage}, + // needs root + {"install",&DoInstall}, + {"remove", &DoInstall}, + {"update",&DoUpdate}, + {"upgrade",&DoUpgradeWithAllowNewPackages}, + // helper + {"moo",&DoMoo}, + {"help",&ShowHelp}, + {0,0}}; + + std::vector<CommandLine::Args> Args = getCommandArgs("apt", CommandLine::GetCommand(Cmds, argc, argv)); + + if(!isatty(1)) + { + std::cerr << std::endl + << "WARNING WARNING " + << argv[0] + << " is *NOT* intended for scripts " + << "use at your own peril^Wrisk" + << std::endl + << std::endl; + } + + InitOutput(); + + // Set up gettext support + setlocale(LC_ALL,""); + textdomain(PACKAGE); + + if(pkgInitConfig(*_config) == false) + { + _error->DumpErrors(); + return 100; + } + + // FIXME: move into a new libprivate/private-install.cc:Install() + _config->Set("DPkgPM::Progress", "1"); + _config->Set("Apt::Color", "1"); + + // Parse the command line and initialize the package library + CommandLine CmdL(Args.data(), _config); + if (CmdL.Parse(argc, argv) == false || + pkgInitSystem(*_config, _system) == false) + { + _error->DumpErrors(); + return 100; + } + + // See if the help should be shown + if (_config->FindB("help") == true || + _config->FindB("version") == true || + CmdL.FileSize() == 0) + { + ShowHelp(CmdL); + return 0; + } + + // see if we are in simulate mode + CheckSimulateMode(CmdL); + + // parse args + CmdL.DispatchArg(Cmds); + + // Print any errors or warnings found during parsing + bool const Errors = _error->PendingError(); + if (_config->FindI("quiet",0) > 0) + _error->DumpErrors(); + else + _error->DumpErrors(GlobalError::DEBUG); + return Errors == true ? 100 : 0; +} + /*}}}*/ diff --git a/cmdline/makefile b/cmdline/makefile index 460a71240..e77ad5669 100644 --- a/cmdline/makefile +++ b/cmdline/makefile @@ -5,30 +5,37 @@ SUBDIR=cmdline # Bring in the default rules include ../buildlib/defaults.mak +# The apt program +PROGRAM=apt +SLIBS = -lapt-pkg -lapt-private $(INTLLIBS) +LIB_MAKES = apt-pkg/makefile +SOURCE = apt.cc +include $(PROGRAM_H) + # The apt-cache program PROGRAM=apt-cache -SLIBS = -lapt-pkg $(INTLLIBS) +SLIBS = -lapt-pkg -lapt-private $(INTLLIBS) LIB_MAKES = apt-pkg/makefile SOURCE = apt-cache.cc include $(PROGRAM_H) # The apt-get program PROGRAM=apt-get -SLIBS = -lapt-pkg $(INTLLIBS) +SLIBS = -lapt-pkg -lapt-private $(INTLLIBS) LIB_MAKES = apt-pkg/makefile -SOURCE = apt-get.cc acqprogress.cc +SOURCE = apt-get.cc include $(PROGRAM_H) # The apt-config program PROGRAM=apt-config -SLIBS = -lapt-pkg $(INTLLIBS) +SLIBS = -lapt-pkg -lapt-private $(INTLLIBS) LIB_MAKES = apt-pkg/makefile SOURCE = apt-config.cc include $(PROGRAM_H) # The apt-cdrom program PROGRAM=apt-cdrom -SLIBS = -lapt-pkg $(INTLLIBS) +SLIBS = -lapt-pkg -lapt-private $(INTLLIBS) LIB_MAKES = apt-pkg/makefile SOURCE = apt-cdrom.cc include $(PROGRAM_H) @@ -41,7 +48,7 @@ include $(COPY_H) # The apt-mark program PROGRAM=apt-mark -SLIBS = -lapt-pkg $(INTLLIBS) +SLIBS = -lapt-pkg -lapt-private $(INTLLIBS) LIB_MAKES = apt-pkg/makefile SOURCE = apt-mark.cc include $(PROGRAM_H) |