From b917917067e757c4479a344a263ef7cf43c00866 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 12 Aug 2013 23:24:08 +0200 Subject: squash merge of the feature/apt-binary branch without the changes from experimental --- apt-private/acqprogress.cc | 309 ++++++++++++++ apt-private/acqprogress.h | 38 ++ apt-private/makefile | 28 ++ apt-private/private-cachefile.cc | 109 +++++ apt-private/private-cachefile.h | 51 +++ apt-private/private-cacheset.cc | 63 +++ apt-private/private-cacheset.h | 265 ++++++++++++ apt-private/private-cmndline.cc | 268 ++++++++++++ apt-private/private-cmndline.h | 10 + apt-private/private-install.cc | 852 +++++++++++++++++++++++++++++++++++++++ apt-private/private-install.h | 181 +++++++++ apt-private/private-list.cc | 158 ++++++++ apt-private/private-list.h | 9 + apt-private/private-main.cc | 26 ++ apt-private/private-main.h | 9 + apt-private/private-moo.cc | 193 +++++++++ apt-private/private-moo.h | 12 + apt-private/private-output.cc | 753 ++++++++++++++++++++++++++++++++++ apt-private/private-output.h | 49 +++ apt-private/private-search.cc | 99 +++++ apt-private/private-search.h | 9 + apt-private/private-show.cc | 122 ++++++ apt-private/private-show.h | 12 + apt-private/private-update.cc | 93 +++++ apt-private/private-update.h | 8 + apt-private/private-upgrade.cc | 47 +++ apt-private/private-upgrade.h | 11 + 27 files changed, 3784 insertions(+) create mode 100644 apt-private/acqprogress.cc create mode 100644 apt-private/acqprogress.h create mode 100644 apt-private/makefile create mode 100644 apt-private/private-cachefile.cc create mode 100644 apt-private/private-cachefile.h create mode 100644 apt-private/private-cacheset.cc create mode 100644 apt-private/private-cacheset.h create mode 100644 apt-private/private-cmndline.cc create mode 100644 apt-private/private-cmndline.h create mode 100644 apt-private/private-install.cc create mode 100644 apt-private/private-install.h create mode 100644 apt-private/private-list.cc create mode 100644 apt-private/private-list.h create mode 100644 apt-private/private-main.cc create mode 100644 apt-private/private-main.h create mode 100644 apt-private/private-moo.cc create mode 100644 apt-private/private-moo.h create mode 100644 apt-private/private-output.cc create mode 100644 apt-private/private-output.h create mode 100644 apt-private/private-search.cc create mode 100644 apt-private/private-search.h create mode 100644 apt-private/private-show.cc create mode 100644 apt-private/private-show.h create mode 100644 apt-private/private-update.cc create mode 100644 apt-private/private-update.h create mode 100644 apt-private/private-upgrade.cc create mode 100644 apt-private/private-upgrade.h (limited to 'apt-private') 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "acqprogress.h" +#include + /*}}}*/ + +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 + +#include + +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 + +#include +#include + +#include + +#include "private-output.h" +#include "private-cachefile.h" + +#include + /*}}}*/ + +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 +#include + + +// 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 +#include +#include +#include + +#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 +#include +#include + +#include +#include + +#include "private-output.h" + +#include + +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 > 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 > 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 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 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 + +#include +#include + +#include + +#include +#include + +#include "private-cmndline.h" + +#include + /*}}}*/ + +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 &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 &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 &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 &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 &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 &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 getCommandArgs(char const * const Program, char const * const Cmd)/*{{{*/ +{ + std::vector 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 + +#include + +std::vector 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "private-install.h" +#include "private-cachefile.h" +#include "private-output.h" +#include "private-cacheset.h" +#include "acqprogress.h" + +#include + /*}}}*/ + +// 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 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 const disappearedPkgs = PM->GetDisappearedPackages(); + if (disappearedPkgs.empty() == true) + return true; + + std::string disappear; + for (std::set::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 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 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 +#include +#include + +#include "private-cachefile.h" +#include "private-output.h" + +#include + +#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 > start, std::ostream &out) + { + for (std::list >::const_iterator s = start.begin(); + s != start.end(); ++s) + Cache->GetDepCache()->SetCandidateVersion(s->first); + + bool Success = true; + std::list > Changed; + for (std::list >::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 >::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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "private-cmndline.h" +#include "private-list.h" +#include "private-output.h" +#include "private-cacheset.h" + +#include + /*}}}*/ + +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 filters; + std::vector::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 output_map; + std::map::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( + V.ParentPkg().Name(), outs.str())); + } else { + ListSingleVersion(CacheFile, records, V, outs); + output_map.insert(std::make_pair( + 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 + +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 +#include + +#include +#include "private-main.h" + +#include + +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 + +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 + +#include +#include +#include + +#include +#include + +#include "private-moo.h" +#include "private-output.h" + +#include + /*}}}*/ + +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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "private-output.h" +#include "private-cachefile.h" + +#include + /*}}}*/ + +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 +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 output_map; + std::map::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( + 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 + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 + +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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "private-cachefile.h" +#include "private-output.h" +#include "acqprogress.h" + +#include + /*}}}*/ + +// 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 + +#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 + + +bool DoUpgradeNoNewPackages(CommandLine &CmdL); +bool DoUpgradeWithAllowNewPackages(CommandLine &CmdL); + + +#endif -- cgit v1.2.3 From dd4d9729975fc2de37cd69220bc05efb16badc77 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 15 Aug 2013 13:39:32 +0200 Subject: add PACKAGE_MATCHER_ABI_COMPAT mode for now so that this branch can be merged without breaking ABI --- apt-private/private-list.cc | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'apt-private') diff --git a/apt-private/private-list.cc b/apt-private/private-list.cc index ac72ce51a..c3a21aafc 100644 --- a/apt-private/private-list.cc +++ b/apt-private/private-list.cc @@ -53,6 +53,9 @@ struct PackageSortAlphabetic } }; +#ifdef PACKAGE_MATCHER_ABI_COMPAT +#define PackageMatcher PackageNameMatchesFnmatch +#endif class PackageNameMatcher : public Matcher { public: @@ -61,11 +64,16 @@ class PackageNameMatcher : public Matcher for(int i=0; patterns[i] != NULL; i++) { std::string pattern = patterns[i]; +#ifdef PACKAGE_MATCHER_ABI_COMPAT + APT::CacheFilter::PackageNameMatchesFnmatch *cachefilter = NULL; + cachefilter = new APT::CacheFilter::PackageNameMatchesFnmatch(pattern); +#else 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); +#endif filters.push_back(cachefilter); } } @@ -88,6 +96,7 @@ class PackageNameMatcher : public Matcher private: std::vector filters; std::vector::const_iterator J; + #undef PackageMatcher }; -- cgit v1.2.3 From 80e8d923ebc8d5f3f84eb3f922b28ca309c25026 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 26 Aug 2013 18:52:06 +0200 Subject: apt-private/private-cmndline.cc: fix typo: s/deselect-upgrade/dselect-upgrade/ --- apt-private/private-cmndline.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-private') diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index aceb865d5..8902f07d5 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -114,7 +114,7 @@ bool addArgumentsAPTConfig(std::vector &Args, char const * co bool addArgumentsAPTGet(std::vector &Args, char const * const Cmd)/*{{{*/ { if (CmdMatches("install", "remove", "purge", "upgrade", "dist-upgrade", - "deselect-upgrade", "autoremove")) + "dselect-upgrade", "autoremove")) { addArg(0, "dpkg-progress", "DpkgPM::Progress", 0); addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0); -- cgit v1.2.3 From be0270de5f676152e9315d858a2d68b1a61cc37c Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 27 Aug 2013 08:38:05 +0200 Subject: use SPtr to simply code --- apt-private/private-install.cc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'apt-private') diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index d5052fcc0..4e29fbbf6 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -595,7 +595,7 @@ bool DoInstall(CommandLine &CmdL) if (Cache->BrokenCount() != 0) BrokenFix = true; - pkgProblemResolver* Fix = NULL; + SPtr Fix; if (_config->FindB("APT::Get::CallResolver", true) == true) Fix = new pkgProblemResolver(Cache); @@ -628,8 +628,6 @@ bool DoInstall(CommandLine &CmdL) if (_error->PendingError() == true) { helper.showVirtualPackageErrors(Cache); - if (Fix != NULL) - delete Fix; return false; } @@ -663,8 +661,6 @@ bool DoInstall(CommandLine &CmdL) if (_error->PendingError() == true) { - if (Fix != NULL) - delete Fix; return false; } @@ -675,8 +671,6 @@ bool DoInstall(CommandLine &CmdL) { 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).")); } @@ -684,7 +678,6 @@ bool DoInstall(CommandLine &CmdL) { // Call the scored problem resolver Fix->Resolve(true); - delete Fix; } // Now we check the state of the packages, -- cgit v1.2.3 From d8a8f9d7f01c75a7bbad7a488bf359a94291d1de Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 27 Aug 2013 08:50:06 +0200 Subject: allow pkg manipulation in the upgrade/dist-upgrade commandline, e.g. apt-get dist-upgrade 2vcard- 4g8+ --- apt-private/private-install.cc | 62 ++++++++++++++++++++++++++---------------- apt-private/private-install.h | 3 ++ apt-private/private-upgrade.cc | 14 ++++++---- 3 files changed, 50 insertions(+), 29 deletions(-) (limited to 'apt-private') diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 4e29fbbf6..b03f131a4 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -577,19 +577,19 @@ bool DoAutomaticRemove(CacheFile &Cache) } /*}}}*/ +static const unsigned short MOD_REMOVE = 1; +static const unsigned short MOD_INSTALL = 2; +bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache) +{ + std::map verset; + return DoCacheManipulationFromCommandLine(CmdL, Cache, verset); +} - -// DoInstall - Install packages from the command line /*{{{*/ -// --------------------------------------------------------------------- -/* Install named packages */ -bool DoInstall(CommandLine &CmdL) +bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, + std::map &verset) { - 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) @@ -599,9 +599,6 @@ bool DoInstall(CommandLine &CmdL) 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; @@ -622,7 +619,7 @@ bool DoInstall(CommandLine &CmdL) mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-", APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST)); CacheSetHelperAPTGet helper(c0out); - std::map verset = APT::VersionSet::GroupedFromCommandLine(Cache, + verset = APT::VersionSet::GroupedFromCommandLine(Cache, CmdL.FileList + 1, mods, fallback, helper); if (_error->PendingError() == true) @@ -711,6 +708,34 @@ bool DoInstall(CommandLine &CmdL) if (!DoAutomaticRemove(Cache)) return false; + // 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); + + 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; + + std::map verset; + + if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset)) + 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()) @@ -826,15 +851,6 @@ bool DoInstall(CommandLine &CmdL) } - // 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) diff --git a/apt-private/private-install.h b/apt-private/private-install.h index fcf4cbced..439c89712 100644 --- a/apt-private/private-install.h +++ b/apt-private/private-install.h @@ -14,6 +14,9 @@ bool DoInstall(CommandLine &Cmd); +bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, + std::map &verset); +bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache); bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, bool Safety = true); diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc index eb546e3e3..09085c2db 100644 --- a/apt-private/private-upgrade.cc +++ b/apt-private/private-upgrade.cc @@ -13,9 +13,6 @@ packages */ bool DoUpgradeNoNewPackages(CommandLine &CmdL) { - if (CmdL.FileSize() != 1) - return _error->Error(_("The upgrade command takes no arguments")); - CacheFile Cache; if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) return false; @@ -26,6 +23,10 @@ bool DoUpgradeNoNewPackages(CommandLine &CmdL) ShowBroken(c1out,Cache,false); return _error->Error(_("Internal error, AllUpgrade broke stuff")); } + + // parse additional cmdline pkg manipulation switches + if(!DoCacheManipulationFromCommandLine(CmdL, Cache)) + return false; return InstallPackages(Cache,true); } @@ -34,9 +35,6 @@ bool DoUpgradeNoNewPackages(CommandLine &CmdL) // DoSafeUpgrade - Upgrade all packages with install but not remove /*{{{*/ bool DoUpgradeWithAllowNewPackages(CommandLine &CmdL) { - if (CmdL.FileSize() != 1) - return _error->Error(_("The upgrade command takes no arguments")); - CacheFile Cache; if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) return false; @@ -47,6 +45,10 @@ bool DoUpgradeWithAllowNewPackages(CommandLine &CmdL) ShowBroken(c1out,Cache,false); return _error->Error(_("Internal error, AllUpgrade broke stuff")); } + + // parse additional cmdline pkg manipulation switches + if(!DoCacheManipulationFromCommandLine(CmdL, Cache)) + return false; return InstallPackages(Cache,true); } -- cgit v1.2.3 From c8d49419be9ce10ade643370bf29891f76b5c339 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 27 Aug 2013 14:07:52 +0200 Subject: add new "apt-get upgrade --with-allow-new" option The --with-allow-new option maps to APT::Get::UpgradeAllowNew and will allow "apt-get upgrade" to install new packages (but not to delete existing packages) --- apt-private/private-cmndline.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'apt-private') diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index aceb865d5..c0b5a875f 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -163,6 +163,9 @@ bool addArgumentsAPTGet(std::vector &Args, char const * const addArg('s', "no-act", "APT::Get::Simulate", 0); } + if (CmdMatches("upgrade")) + addArg(0, "allow-new", "APT::Get::UpgradeAllowNew", CommandLine::Boolean); + // FIXME: move to the correct command(s) addArg('d',"download-only","APT::Get::Download-Only",0); addArg('y',"yes","APT::Get::Assume-Yes",0); -- cgit v1.2.3 From c678a0443518aa5e8f328f358fca7b35252df84e Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 28 Aug 2013 11:28:40 +0200 Subject: add man-page, improve option, use --with-new-pkgs as the flag --- apt-private/private-cmndline.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'apt-private') diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index c0b5a875f..152256806 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -125,7 +125,8 @@ bool addArgumentsAPTGet(std::vector &Args, char const * const addArg(0, "solver", "APT::Solver", CommandLine::HasArg); if (CmdMatches("upgrade")) { - addArg(0, "allow-new", "APT::Get::UpgradeAllowNew", 0); + addArg(0, "allow-new", "APT::Get::Upgrade-Allow-New", + CommandLine::Boolean); } } else if (CmdMatches("update")) @@ -163,9 +164,6 @@ bool addArgumentsAPTGet(std::vector &Args, char const * const addArg('s', "no-act", "APT::Get::Simulate", 0); } - if (CmdMatches("upgrade")) - addArg(0, "allow-new", "APT::Get::UpgradeAllowNew", CommandLine::Boolean); - // FIXME: move to the correct command(s) addArg('d',"download-only","APT::Get::Download-Only",0); addArg('y',"yes","APT::Get::Assume-Yes",0); -- cgit v1.2.3 From 2004d64720b396ae2dc9d2a7f6bf7859d6d7ee9b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 28 Aug 2013 11:36:44 +0200 Subject: its --with-new-pkgs --- apt-private/private-cmndline.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-private') diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 152256806..b30eeffb7 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -125,7 +125,7 @@ bool addArgumentsAPTGet(std::vector &Args, char const * const addArg(0, "solver", "APT::Solver", CommandLine::HasArg); if (CmdMatches("upgrade")) { - addArg(0, "allow-new", "APT::Get::Upgrade-Allow-New", + addArg(0, "new-pkgs", "APT::Get::Upgrade-Allow-New", CommandLine::Boolean); } } -- cgit v1.2.3 From ee0167c4a0bf0c6de5437d3b641e7e7c0c614f17 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 30 Aug 2013 17:18:20 +0200 Subject: fix vim-style foldmarker Git-Dch: Ignore --- apt-private/private-install.cc | 10 ++-------- apt-private/private-list.cc | 15 +++++++-------- apt-private/private-output.cc | 38 ++++++++++++++++++-------------------- apt-private/private-search.cc | 6 ++++-- apt-private/private-show.cc | 5 +++-- apt-private/private-upgrade.cc | 7 +++---- 6 files changed, 37 insertions(+), 44 deletions(-) (limited to 'apt-private') diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index b03f131a4..9808c3dde 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -94,8 +94,6 @@ static bool CheckAuth(pkgAcquire& Fetcher) 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 @@ -429,8 +427,6 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) return true; } /*}}}*/ - - // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/ // --------------------------------------------------------------------- /* Remove unused automatic packages */ @@ -576,7 +572,7 @@ bool DoAutomaticRemove(CacheFile &Cache) return true; } /*}}}*/ - +// DoCacheManipulationFromCommandLine /*{{{*/ static const unsigned short MOD_REMOVE = 1; static const unsigned short MOD_INSTALL = 2; @@ -585,7 +581,6 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache) std::map verset; return DoCacheManipulationFromCommandLine(CmdL, Cache, verset); } - bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, std::map &verset) { @@ -719,8 +714,7 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, return true; } - - + /*}}}*/ // DoInstall - Install packages from the command line /*{{{*/ // --------------------------------------------------------------------- /* Install named packages */ diff --git a/apt-private/private-list.cc b/apt-private/private-list.cc index c3a21aafc..8c61fcae8 100644 --- a/apt-private/private-list.cc +++ b/apt-private/private-list.cc @@ -42,7 +42,7 @@ #include /*}}}*/ -struct PackageSortAlphabetic +struct PackageSortAlphabetic /*{{{*/ { bool operator () (const pkgCache::PkgIterator &p_lhs, const pkgCache::PkgIterator &p_rhs) @@ -52,12 +52,12 @@ struct PackageSortAlphabetic return (l_name < r_name); } }; - + /*}}}*/ +class PackageNameMatcher : public Matcher /*{{{*/ +{ #ifdef PACKAGE_MATCHER_ABI_COMPAT #define PackageMatcher PackageNameMatchesFnmatch #endif -class PackageNameMatcher : public Matcher -{ public: PackageNameMatcher(const char **patterns) { @@ -98,9 +98,8 @@ private: std::vector::const_iterator J; #undef PackageMatcher }; - - -void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records, + /*}}}*/ +void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ pkgCache::PkgIterator P, std::ostream &outs) { @@ -108,7 +107,7 @@ void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records, Ver.end() == false; Ver++) ListSingleVersion(CacheFile, records, Ver, outs); } - + /*}}}*/ // list - list package based on criteria /*{{{*/ // --------------------------------------------------------------------- bool List(CommandLine &Cmd) diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 659975476..6fadf7274 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -28,8 +28,7 @@ std::ostream c2out(0); std::ofstream devnull("/dev/null"); unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */ - -bool InitOutput() +bool InitOutput() /*{{{*/ { c0out.rdbuf(cout.rdbuf()); c1out.rdbuf(cout.rdbuf()); @@ -60,8 +59,8 @@ bool InitOutput() return true; } - -std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver) + /*}}}*/ +std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver) /*{{{*/ { std::string suite = ""; if (ver && ver.FileList() && ver.FileList()) @@ -77,8 +76,8 @@ std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver) } return suite; } - -std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) + /*}}}*/ +std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/ { pkgDepCache *DepCache = CacheFile.GetDepCache(); pkgDepCache::StateCache &state = (*DepCache)[P]; @@ -94,23 +93,23 @@ std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) flags_str = "-"; return flags_str; } - -std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) + /*}}}*/ +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) + /*}}}*/ +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) + /*}}}*/ +std::string GetVersion(pkgCacheFile &CacheFile, pkgCache::VerIterator V)/*{{{*/ { pkgCache::PkgIterator P = V.ParentPkg(); if (V == P.CurrentVer()) @@ -127,8 +126,8 @@ std::string GetVersion(pkgCacheFile &CacheFile, pkgCache::VerIterator V) return DeNull(V.VerStr()); return "(none)"; } - -std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) + /*}}}*/ +std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/ { pkgPolicy *policy = CacheFile.GetPolicy(); pkgCache::VerIterator inst = P.CurrentVer(); @@ -136,8 +135,8 @@ std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) return inst ? inst.Arch() : cand.Arch(); } - -std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P) + /*}}}*/ +std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/ { pkgPolicy *policy = CacheFile.GetPolicy(); @@ -157,8 +156,8 @@ std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pk } return ShortDescription; } - -void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, + /*}}}*/ +void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ pkgCache::VerIterator V, std::ostream &out) { pkgCache::PkgIterator P = V.ParentPkg(); @@ -230,8 +229,7 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, << std::endl; } } - - + /*}}}*/ // ShowList - Show a list /*{{{*/ // --------------------------------------------------------------------- /* This prints out a string of space separated words with a title and diff --git a/apt-private/private-search.cc b/apt-private/private-search.cc index 6881f482f..ff4140fa7 100644 --- a/apt-private/private-search.cc +++ b/apt-private/private-search.cc @@ -1,3 +1,4 @@ +// Includes /*{{{*/ #include #include #include @@ -34,9 +35,9 @@ #include "private-search.h" #include "private-cacheset.h" + /*}}}*/ - -bool FullTextSearch(CommandLine &CmdL) +bool FullTextSearch(CommandLine &CmdL) /*{{{*/ { pkgCacheFile CacheFile; pkgCache *Cache = CacheFile.GetPkgCache(); @@ -97,3 +98,4 @@ bool FullTextSearch(CommandLine &CmdL) return true; } + /*}}}*/ diff --git a/apt-private/private-show.cc b/apt-private/private-show.cc index e26a2b30a..7f4beb7d0 100644 --- a/apt-private/private-show.cc +++ b/apt-private/private-show.cc @@ -1,3 +1,4 @@ +// Includes /*{{{*/ #include #include #include @@ -23,6 +24,7 @@ #include "private-output.h" #include "private-cacheset.h" + /*}}}*/ namespace APT { namespace Cmd { @@ -87,8 +89,7 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V, return true; } /*}}}*/ - -bool ShowPackage(CommandLine &CmdL) +bool ShowPackage(CommandLine &CmdL) /*{{{*/ { pkgCacheFile CacheFile; CacheSetHelperVirtuals helper(true, GlobalError::NOTICE); diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc index 09085c2db..9a5286b57 100644 --- a/apt-private/private-upgrade.cc +++ b/apt-private/private-upgrade.cc @@ -1,13 +1,13 @@ - +// Includes /*{{{*/ #include #include "private-install.h" #include "private-cachefile.h" #include "private-upgrade.h" #include "private-output.h" + /*}}}*/ - -// DoUpgradeNoNewPackages - Upgrade all packages /*{{{*/ +// DoUpgradeNoNewPackages - Upgrade all packages /*{{{*/ // --------------------------------------------------------------------- /* Upgrade all packages without installing new packages or erasing old packages */ @@ -31,7 +31,6 @@ bool DoUpgradeNoNewPackages(CommandLine &CmdL) return InstallPackages(Cache,true); } /*}}}*/ - // DoSafeUpgrade - Upgrade all packages with install but not remove /*{{{*/ bool DoUpgradeWithAllowNewPackages(CommandLine &CmdL) { -- cgit v1.2.3 From 58c2833fed05dd044a4a937271fb6a8d639fa863 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 10 Sep 2013 17:41:01 +0200 Subject: Fix regression of "apt-cache unmet -i", thanks to Daniel Schepler (closes: #722324) --- apt-private/private-cmndline.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'apt-private') diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 8902f07d5..e8a21cb0c 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -62,8 +62,12 @@ bool addArgumentsAPTCache(std::vector &Args, char const * con { addArg(0, "all-names", "APT::Cache::AllNames", 0); } + else if (CmdMatches("unmet")) + { + addArg('i', "important", "APT::Cache::Important", 0); + } else if (CmdMatches("gencaches", "showsrc", "showpkg", "stats", "dump", - "dumpavail", "unmet", "showauto", "policy", "madison")) + "dumpavail", "showauto", "policy", "madison")) ; else return false; -- cgit v1.2.3 From ad1d6bfbd75e1121ccfdd3ae159254d799825d37 Mon Sep 17 00:00:00 2001 From: Christian PERRIER Date: Mon, 23 Sep 2013 07:06:18 +0200 Subject: Fix typo in apt-private/private-show.cc. Thanks to Benjamin Keresa. Closes: #724073 --- apt-private/private-show.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-private') diff --git a/apt-private/private-show.cc b/apt-private/private-show.cc index 7f4beb7d0..ddc75dbeb 100644 --- a/apt-private/private-show.cc +++ b/apt-private/private-show.cc @@ -103,7 +103,7 @@ bool ShowPackage(CommandLine &CmdL) /*{{{*/ Pkg != helper.virtualPkgs.end(); ++Pkg) { c1out << "Package: " << Pkg.FullName(true) << std::endl; - c1out << "State: " << _("not a real pacakge (virtual)") << std::endl; + c1out << "State: " << _("not a real package (virtual)") << std::endl; // FIXME: show providers, see private-cacheset.h // CacheSetHelperAPTGet::showVirtualPackageErrors() } -- cgit v1.2.3 From ac69a4d8aa837d1ab31447bbaa9a7ea95917bac9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 26 Sep 2013 14:56:45 +0200 Subject: print-uris prints regardless of quiet-level again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While the InstallPackages code was moved from apt-get into the private library the output was moved from (std::)cout to c1out which isn't shown in quiet level 2 (and above), so we flip back to std::cout to ensure that it is always printed as you are not going to use --print-uris if you don't want to see the uris… Closes: 722207 --- apt-private/private-install.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-private') diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 9808c3dde..c07d060f3 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -299,7 +299,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) { pkgAcquire::UriIterator I = Fetcher.UriBegin(); for (; I != Fetcher.UriEnd(); ++I) - c1out << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << + std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl; return true; } -- cgit v1.2.3 From 4fb66d8731045e6ad90ef70dff45bd28815714fc Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 1 Oct 2013 11:30:56 +0200 Subject: rename "--dpkg-progress" to "--show-progress" and document it in apt-get.8 --- apt-private/private-cmndline.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-private') diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 8902f07d5..eedabe20c 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -116,7 +116,7 @@ bool addArgumentsAPTGet(std::vector &Args, char const * const if (CmdMatches("install", "remove", "purge", "upgrade", "dist-upgrade", "dselect-upgrade", "autoremove")) { - addArg(0, "dpkg-progress", "DpkgPM::Progress", 0); + addArg(0, "show-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); -- cgit v1.2.3 From 866893a619e00966ae6b1549c4bfce92d6c17db1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 3 Oct 2013 14:45:41 +0200 Subject: put fetch errors in 'source' on our errorstack refactor the fetching process so that it looks more like the others we have in the hope that we can reuse code in the future. This is a soft interface change as 'source' previously printed errors directly on stderr, while it will now push it onto our usual error stack. --- apt-private/makefile | 2 +- apt-private/private-download.cc | 96 +++++++++++++++++++++++++++++++++++++++++ apt-private/private-download.h | 9 ++++ apt-private/private-install.cc | 72 +++---------------------------- 4 files changed, 111 insertions(+), 68 deletions(-) create mode 100644 apt-private/private-download.cc create mode 100644 apt-private/private-download.h (limited to 'apt-private') diff --git a/apt-private/makefile b/apt-private/makefile index 8feb1ce6c..1d179f0b2 100644 --- a/apt-private/makefile +++ b/apt-private/makefile @@ -17,7 +17,7 @@ MAJOR=0.0 MINOR=0 SLIBS=$(PTHREADLIB) -lapt-pkg -PRIVATES=list install output cachefile cacheset update upgrade cmndline moo search show main +PRIVATES=list install download output cachefile cacheset update upgrade cmndline moo search show main SOURCE += $(foreach private, $(PRIVATES), private-$(private).cc) HEADERS += $(foreach private, $(PRIVATES), private-$(private).h) diff --git a/apt-private/private-download.cc b/apt-private/private-download.cc new file mode 100644 index 000000000..f02991cde --- /dev/null +++ b/apt-private/private-download.cc @@ -0,0 +1,96 @@ +// Include Files /*{{{*/ +#include + +#include +#include +#include +#include +#include + +#include "private-output.h" + +#include + +#include +#include +#include + +#include + /*}}}*/ + +// CheckAuth - check if each download comes form a trusted source /*{{{*/ +bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser) +{ + 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 (PromptUser == false) + return _error->Error(_("Some packages could not be authenticated")); + + 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")); +} + /*}}}*/ +bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure)/*{{{*/ +{ + pkgAcquire::RunResult res; + if(PulseInterval > 0) + res = Fetcher.Run(PulseInterval); + else + res = Fetcher.Run(); + + if (res == pkgAcquire::Failed) + return false; + + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); + I != Fetcher.ItemsEnd(); ++I) + { + + if ((*I)->Status == pkgAcquire::Item::StatDone && + (*I)->Complete == true) + continue; + + if (TransientNetworkFailure != NULL && (*I)->Status == pkgAcquire::Item::StatIdle) + { + *TransientNetworkFailure = true; + continue; + } + + ::URI uri((*I)->DescURI()); + uri.User.clear(); + uri.Password.clear(); + std::string descUri = std::string(uri); + _error->Error(_("Failed to fetch %s %s\n"), descUri.c_str(), + (*I)->ErrorText.c_str()); + + if (Failure != NULL) + *Failure = true; + } + + return true; +} + /*}}}*/ diff --git a/apt-private/private-download.h b/apt-private/private-download.h new file mode 100644 index 000000000..b8cc8da1e --- /dev/null +++ b/apt-private/private-download.h @@ -0,0 +1,9 @@ +#ifndef APT_PRIVATE_DOWNLOAD_H +#define APT_PRIVATE_DOWNLOAD_H + +#include + +bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser); +bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure); + +#endif diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index c07d060f3..9adad45af 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -42,6 +42,7 @@ #include #include "private-install.h" +#include "private-download.h" #include "private-cachefile.h" #include "private-output.h" #include "private-cacheset.h" @@ -50,50 +51,6 @@ #include /*}}}*/ -// 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 @@ -304,7 +261,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) return true; } - if (!CheckAuth(Fetcher)) + if (!CheckAuth(Fetcher, true)) return false; /* Unlock the dpkg lock if we are not going to be doing an install @@ -336,29 +293,10 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) 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; - } + bool Failed = false; + if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false) + return false; /* If we are in no download mode and missing files and there were 'failures' then the user must specify -m. Furthermore, there -- cgit v1.2.3 From 3a7a206f40b8fda475e39566fc220fe8c5b59a17 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 3 Oct 2013 22:23:11 +0200 Subject: do not ++ on erased package pointers in autoremove Symptom: In an Ubuntu precise chroot (like on travis-ci) test-bug-613420-new-garbage-dependency segfaults in a std::set operator++ on an iterator we have erased previously (but not if run under gdb of course) --- apt-private/private-install.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'apt-private') diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 9adad45af..643a6b370 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -438,15 +438,15 @@ bool DoAutomaticRemove(CacheFile &Cache) do { Changed = false; for (APT::PackageSet::const_iterator Pkg = tooMuch.begin(); - Pkg != tooMuch.end() && Changed == false; ++Pkg) + Pkg != tooMuch.end(); ++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 (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P) + { for (pkgCache::DepIterator R = P.RevDependsList(); R.end() == false; ++R) { @@ -465,7 +465,11 @@ bool DoAutomaticRemove(CacheFile &Cache) Changed = true; break; } + if (Changed == true) + break; } + if (Changed == true) + break; } } while (Changed == true); } -- cgit v1.2.3