#include <apt-pkg/cachefile.h>
#include <apt-pkg/pkgrecords.h>
#include <apt-pkg/policy.h>
+#include <apt-pkg/depcache.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cacheiterators.h>
+#include <apt-private/private-output.h>
+#include <apt-private/private-cachefile.h>
+
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <iomanip>
#include <iostream>
-#include <locale.h>
#include <langinfo.h>
#include <unistd.h>
+#include <signal.h>
+#include <sys/ioctl.h>
-#include "private-output.h"
-#include "private-cachefile.h"
+#include <sstream>
#include <apti18n.h>
/*}}}*/
std::ostream c1out(0);
std::ostream c2out(0);
std::ofstream devnull("/dev/null");
+
+
unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */
-bool InitOutput() /*{{{*/
+// SigWinch - Window size change signal handler /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static void SigWinch(int)
+{
+ // Riped from GNU ls
+#ifdef TIOCGWINSZ
+ struct winsize ws;
+
+ if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
+ ScreenWidth = ws.ws_col - 1;
+#endif
+}
+ /*}}}*/
+bool InitOutput(std::basic_streambuf<char> * const out) /*{{{*/
{
if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
_config->Set("quiet","1");
- c0out.rdbuf(cout.rdbuf());
- c1out.rdbuf(cout.rdbuf());
- c2out.rdbuf(cout.rdbuf());
+ c0out.rdbuf(out);
+ c1out.rdbuf(out);
+ c2out.rdbuf(out);
if (_config->FindI("quiet",0) > 0)
c0out.rdbuf(devnull.rdbuf());
if (_config->FindI("quiet",0) > 1)
c1out.rdbuf(devnull.rdbuf());
+ // deal with window size changes
+ signal(SIGWINCH,SigWinch);
+ SigWinch(0);
+
if(!isatty(1))
{
_config->Set("APT::Color", "false");
return true;
}
/*}}}*/
-static std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver) /*{{{*/
+static std::string GetArchiveSuite(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator ver) /*{{{*/
{
std::string suite = "";
- if (ver && ver.FileList() && ver.FileList())
+ if (ver && ver.FileList())
{
pkgCache::VerFileIterator VF = ver.FileList();
for (; VF.end() == false ; ++VF)
std::string flags_str;
if (state.NowBroken())
flags_str = "B";
- if (P.CurrentVer() && state.Upgradable())
+ if (P.CurrentVer() && state.Upgradable() && state.CandidateVer != NULL)
flags_str = "g";
else if (P.CurrentVer() != NULL)
flags_str = "i";
return cand ? cand.VerStr() : "(none)";
}
/*}}}*/
-static std::string GetInstalledVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
+static std::string GetInstalledVersion(pkgCacheFile &/*CacheFile*/, pkgCache::PkgIterator P)/*{{{*/
{
pkgCache::VerIterator inst = P.CurrentVer();
return inst ? inst.VerStr() : "(none)";
}
/*}}}*/
-static std::string GetVersion(pkgCacheFile &CacheFile, pkgCache::VerIterator V)/*{{{*/
+static std::string GetVersion(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator V)/*{{{*/
{
pkgCache::PkgIterator P = V.ParentPkg();
if (V == P.CurrentVer())
/*}}}*/
static 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();
+ if (P->CurrentVer == 0)
+ {
+ pkgDepCache * const DepCache = CacheFile.GetDepCache();
+ pkgDepCache::StateCache const &state = (*DepCache)[P];
+ if (state.CandidateVer != NULL)
+ {
+ pkgCache::VerIterator const CandV(CacheFile, state.CandidateVer);
+ return CandV.Arch();
+ }
+ else
+ {
+ pkgCache::VerIterator const V = P.VersionList();
+ if (V.end() == false)
+ return V.Arch();
+ else
+ return P.Arch();
+ }
+ }
+ else
+ return P.CurrentVer().Arch();
}
/*}}}*/
static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
std::string ShortDescription = "(none)";
if(ver)
{
- pkgCache::DescIterator Desc = ver.TranslatedDescription();
- pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
-
- ShortDescription = parser.ShortDesc();
+ pkgCache::DescIterator const Desc = ver.TranslatedDescription();
+ if (Desc.end() == false)
+ {
+ pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
+ ShortDescription = parser.ShortDesc();
+ }
}
return ShortDescription;
}
/*}}}*/
-void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/
- pkgCache::VerIterator V, std::ostream &out,
- bool include_summary)
+static std::string GetLongDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
{
- pkgCache::PkgIterator P = V.ParentPkg();
+ pkgPolicy *policy = CacheFile.GetPolicy();
- pkgDepCache *DepCache = CacheFile.GetDepCache();
- pkgDepCache::StateCache &state = (*DepCache)[P];
+ pkgCache::VerIterator ver;
+ if (P->CurrentVer != 0)
+ ver = P.CurrentVer();
+ else
+ ver = policy->GetCandidateVer(P);
- std::string suite = GetArchiveSuite(CacheFile, V);
- std::string name_str = P.Name();
+ std::string const EmptyDescription = "(none)";
+ if(ver.end() == true)
+ return EmptyDescription;
- if (_config->FindB("APT::Cmd::use-format", false))
+ pkgCache::DescIterator const Desc = ver.TranslatedDescription();
+ if (Desc.end() == 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();
- std::string VersionStr = GetVersion(CacheFile, V);
- std::string CandidateVerStr = GetCandidateVersion(CacheFile, P);
- std::string InstalledVerStr = GetInstalledVersion(CacheFile, P);
- std::string StatusStr;
- if(P.CurrentVer() == V && state.Upgradable()) {
- strprintf(StatusStr, _("[installed,upgradable to: %s]"),
- CandidateVerStr.c_str());
- } else if (P.CurrentVer() == V) {
- if(!V.Downloadable())
- StatusStr = _("[installed,local]");
- else
- if(V.Automatic() && state.Garbage)
- StatusStr = _("[installed,auto-removable]");
- else if (state.Flags & pkgCache::Flag::Auto)
- StatusStr = _("[installed,automatic]");
- else
- StatusStr = _("[installed]");
- } else if (P.CurrentVer() &&
- policy->GetCandidateVer(P) == V &&
- state.Upgradable()) {
- strprintf(StatusStr, _("[upgradable from: %s]"),
- InstalledVerStr.c_str());
- } else {
- if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
- StatusStr = _("[residual-config]");
- else
- StatusStr = "";
- }
- out << std::setiosflags(std::ios::left)
- << _config->Find("APT::Color::Highlight", "")
- << name_str
- << _config->Find("APT::Color::Neutral", "")
- << "/" << suite
- << " "
- << VersionStr << " "
- << GetArchitecture(CacheFile, P);
- if (StatusStr != "")
- out << " " << StatusStr;
- if (include_summary)
- {
- out << std::endl
- << " " << GetShortDescription(CacheFile, records, P)
- << std::endl;
- }
+ pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
+ std::string const longdesc = parser.LongDesc();
+ if (longdesc.empty() == false)
+ return SubstVar(longdesc, "\n ", "\n ");
}
+ return EmptyDescription;
}
/*}}}*/
-// 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)
+void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/
+ pkgCache::VerIterator const &V, std::ostream &out,
+ std::string const &format)
{
- 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;
- }
+ pkgCache::PkgIterator const P = V.ParentPkg();
+ pkgDepCache * const DepCache = CacheFile.GetDepCache();
+ pkgDepCache::StateCache const &state = (*DepCache)[P];
- // 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())
+ std::string output;
+ if (_config->FindB("APT::Cmd::use-format", false))
+ output = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
+ else
+ output = format;
+
+ // FIXME: some of these names are really icky – and all is nowhere documented
+ output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
+ output = SubstVar(output, "${Package}", P.Name());
+ std::string const ArchStr = GetArchitecture(CacheFile, P);
+ output = SubstVar(output, "${Architecture}", ArchStr);
+ std::string const InstalledVerStr = GetInstalledVersion(CacheFile, P);
+ output = SubstVar(output, "${installed:Version}", InstalledVerStr);
+ std::string const CandidateVerStr = GetCandidateVersion(CacheFile, P);
+ output = SubstVar(output, "${candidate:Version}", CandidateVerStr);
+ std::string const VersionStr = GetVersion(CacheFile, V);
+ output = SubstVar(output, "${Version}", VersionStr);
+ output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
+
+ std::string StatusStr = "";
+ if (P->CurrentVer != 0)
{
- 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;
+ if (P.CurrentVer() == V)
+ {
+ if (state.Upgradable() && state.CandidateVer != NULL)
+ strprintf(StatusStr, _("[installed,upgradable to: %s]"),
+ CandidateVerStr.c_str());
+ else if (V.Downloadable() == false)
+ StatusStr = _("[installed,local]");
+ else if(V.Automatic() == true && state.Garbage == true)
+ StatusStr = _("[installed,auto-removable]");
+ else if ((state.Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
+ StatusStr = _("[installed,automatic]");
+ else
+ StatusStr = _("[installed]");
}
- }
-
- return false;
+ else if (state.CandidateVer == V && state.Upgradable())
+ strprintf(StatusStr, _("[upgradable from: %s]"),
+ InstalledVerStr.c_str());
+ }
+ else if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
+ StatusStr = _("[residual-config]");
+ output = SubstVar(output, "${apt:Status}", StatusStr);
+ output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", ""));
+ output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", ""));
+ output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
+ if (output.find("${LongDescription}") != string::npos)
+ output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P));
+ output = SubstVar(output, "${ }${ }", "${ }");
+ output = SubstVar(output, "${ }\n", "\n");
+ output = SubstVar(output, "${ }", " ");
+ if (APT::String::Endswith(output, " ") == true)
+ output.erase(output.length() - 1);
+
+ out << output;
}
/*}}}*/
// ShowBroken - Debugging aide /*{{{*/
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)
+static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
{
- if (Cache->BrokenCount() == 0)
+ if (Now == true)
+ {
+ if ((*Cache)[Pkg].NowBroken() == false)
+ return;
+ }
+ else
+ {
+ if ((*Cache)[Pkg].InstBroken() == false)
+ return;
+ }
+
+ // Print out each package and the failed dependencies
+ out << " " << Pkg.FullName(true) << " :";
+ unsigned const Indent = Pkg.FullName(true).size() + 3;
+ bool First = true;
+ pkgCache::VerIterator Ver;
+
+ if (Now == true)
+ Ver = Pkg.CurrentVer();
+ else
+ Ver = (*Cache)[Pkg].InstVerIter(*Cache);
+
+ if (Ver.end() == true)
+ {
+ out << endl;
return;
+ }
- out << _("The following packages have unmet dependencies:") << endl;
- for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+ for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
{
- pkgCache::PkgIterator I(Cache,Cache.List[J]);
-
+ // 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[I].NowBroken() == false)
+ if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
continue;
}
else
{
- if (Cache[I].InstBroken() == false)
+ if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
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;)
+
+ bool FirstOr = true;
+ while (1)
{
- // Compute a single dependency element (glob or)
- pkgCache::DepIterator Start;
- pkgCache::DepIterator End;
- D.GlobOr(Start,End); // advances D
+ if (First == false)
+ for (unsigned J = 0; J != Indent; J++)
+ out << ' ';
+ First = false;
- if (Cache->IsImportantDep(End) == false)
- continue;
-
- if (Now == true)
+ if (FirstOr == false)
{
- if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
- continue;
+ 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)
{
- 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;
+ out << ' ';
+ pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
+ if (Now == true)
+ Ver = Targ.CurrentVer();
- if (FirstOr == false)
+ if (Ver.end() == false)
{
- for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
- out << ' ';
+ if (Now == true)
+ ioprintf(out,_("but %s is installed"),Ver.VerStr());
+ else
+ ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
}
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 ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
{
- if (Now == true)
- ioprintf(out,_("but %s is installed"),Ver.VerStr());
+ if (Targ->ProvidesList == 0)
+ out << _("but it is not installable");
else
- ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
- }
+ out << _("but it is a virtual package");
+ }
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"));
- }
+ 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;
- }
- }
- }
+ }
+
+ if (Start != End)
+ out << _(" or");
+ out << endl;
+
+ if (Start == End)
+ break;
+ ++Start;
+ }
+ }
+}
+void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
+{
+ if (Cache->BrokenCount() == 0)
+ return;
+
+ out << _("The following packages have unmet dependencies:") << endl;
+ SortedPackageUniverse Universe(Cache);
+ for (auto const &Pkg: Universe)
+ ShowBrokenPackage(out, &Cache, Pkg, Now);
+}
+void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
+{
+ if (Cache->BrokenCount() == 0)
+ return;
+
+ out << _("The following packages have unmet dependencies:") << endl;
+ APT::PackageUniverse Universe(Cache);
+ for (auto const &Pkg: Universe)
+ ShowBrokenPackage(out, &Cache, Pkg, Now);
}
/*}}}*/
// 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);
+ SortedPackageUniverse Universe(Cache);
+ ShowList(out,_("The following NEW packages will be installed:"), Universe,
+ [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); },
+ &PrettyFullName,
+ CandidateVersion(&Cache));
}
/*}}}*/
// 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);
+ SortedPackageUniverse Universe(Cache);
+ ShowList(out,_("The following packages will be REMOVED:"), Universe,
+ [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].Delete(); },
+ [&Cache](pkgCache::PkgIterator const &Pkg)
+ {
+ std::string str = PrettyFullName(Pkg);
+ if (((*Cache)[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
+ str.append("*");
+ return str;
+ },
+ CandidateVersion(&Cache));
}
/*}}}*/
// 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);
+ SortedPackageUniverse Universe(Cache);
+ ShowList(out,_("The following packages have been kept back:"), Universe,
+ [&Cache](pkgCache::PkgIterator const &Pkg)
+ {
+ return Cache[Pkg].Upgrade() == false &&
+ Cache[Pkg].Upgradable() == true &&
+ Pkg->CurrentVer != 0 &&
+ Cache[Pkg].Delete() == false;
+ },
+ &PrettyFullName,
+ CurrentToCandidateVersion(&Cache));
}
/*}}}*/
// 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);
+ SortedPackageUniverse Universe(Cache);
+ ShowList(out,_("The following packages will be upgraded:"), Universe,
+ [&Cache](pkgCache::PkgIterator const &Pkg)
+ {
+ return Cache[Pkg].Upgrade() == true && Cache[Pkg].NewInstall() == false;
+ },
+ &PrettyFullName,
+ CurrentToCandidateVersion(&Cache));
}
/*}}}*/
// 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);
+ SortedPackageUniverse Universe(Cache);
+ return ShowList(out,_("The following packages will be DOWNGRADED:"), Universe,
+ [&Cache](pkgCache::PkgIterator const &Pkg)
+ {
+ return Cache[Pkg].Downgrade() == true && Cache[Pkg].NewInstall() == false;
+ },
+ &PrettyFullName,
+ CurrentToCandidateVersion(&Cache));
}
/*}}}*/
// 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);
+ SortedPackageUniverse Universe(Cache);
+ return ShowList(out,_("The following held packages will be changed:"), Universe,
+ [&Cache](pkgCache::PkgIterator const &Pkg)
+ {
+ return Pkg->SelectedState == pkgCache::State::Hold &&
+ Cache[Pkg].InstallVer != (pkgCache::Version *)Pkg.CurrentVer();
+ },
+ &PrettyFullName,
+ CurrentToCandidateVersion(&Cache));
}
/*}}}*/
// 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.
+ all essential packages and their dependents that are to be removed.
It is insanely risky to remove the dependents of an essential package! */
+struct APT_HIDDEN PrettyFullNameWithDue {
+ std::map<unsigned long long, pkgCache::PkgIterator> due;
+ PrettyFullNameWithDue() {}
+ std::string operator() (pkgCache::PkgIterator const &Pkg)
+ {
+ std::string const A = PrettyFullName(Pkg);
+ std::map<unsigned long long, pkgCache::PkgIterator>::const_iterator d = due.find(Pkg->ID);
+ if (d == due.end())
+ return A;
+
+ std::string const B = PrettyFullName(d->second);
+ std::ostringstream outstr;
+ ioprintf(outstr, _("%s (due to %s)"), A.c_str(), B.c_str());
+ return outstr.str();
+ }
+};
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++)
+ std::vector<bool> Added(Cache->Head().PackageCount, false);
+ APT::PackageDeque pkglist;
+ PrettyFullNameWithDue withdue;
+
+ SortedPackageUniverse Universe(Cache);
+ for (pkgCache::PkgIterator const &I: Universe)
{
- 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 (Cache[I].Delete() == false)
+ continue;
+
+ if (Added[I->ID] == false)
{
- if (Added[I->ID] == false)
- {
- Added[I->ID] = true;
- List += I.FullName(true) + " ";
- //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
- }
+ Added[I->ID] = true;
+ pkglist.insert(I);
}
- else
- continue;
if (I->CurrentVer == 0)
continue;
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"; ???
- }
- }
+
+ pkglist.insert(P);
+ withdue.due[P->ID] = I;
+ }
+ }
}
-
- 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);
+ "This should NOT be done unless you know exactly what you are doing!"),
+ pkglist, &AlwaysTrue, withdue, &EmptyString);
}
-
/*}}}*/
// Stats - Show some statistics /*{{{*/
// ---------------------------------------------------------------------
// YnPrompt - Yes No Prompt. /*{{{*/
// ---------------------------------------------------------------------
/* Returns true on a Yes.*/
-bool YnPrompt(bool Default)
+bool YnPrompt(char const * const Question, bool Default)
{
+ auto const AssumeYes = _config->FindB("APT::Get::Assume-Yes",false);
+ auto const AssumeNo = _config->FindB("APT::Get::Assume-No",false);
+ // if we ask interactively, show warnings/notices before the question
+ if (AssumeYes == false && AssumeNo == false)
+ {
+ if (_config->FindI("quiet",0) > 0)
+ _error->DumpErrors(c2out);
+ else
+ _error->DumpErrors(c2out, GlobalError::DEBUG);
+ }
+
+ c2out << Question << std::flush;
+
/* 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");
free(language);
}
- if (_config->FindB("APT::Get::Assume-Yes",false) == true)
+ if (AssumeYes)
{
// 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)
+ else if (AssumeNo)
{
// TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
c1out << _("N") << std::endl;
// AnalPrompt - Annoying Yes No Prompt. /*{{{*/
// ---------------------------------------------------------------------
/* Returns true on a Yes.*/
-bool AnalPrompt(const char *Text)
+bool AnalPrompt(std::string const &Question, const char *Text)
{
+ if (_config->FindI("quiet",0) > 0)
+ _error->DumpErrors(c2out);
+ else
+ _error->DumpErrors(c2out, GlobalError::DEBUG);
+ c2out << Question << std::flush;
+
char Buf[1024];
std::cin.getline(Buf,sizeof(Buf));
if (strcmp(Buf,Text) == 0)
return false;
}
/*}}}*/
+
+std::string PrettyFullName(pkgCache::PkgIterator const &Pkg)
+{
+ return Pkg.FullName(true);
+}
+std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg)
+{
+ return (*Cache)[Pkg].CandVersion;
+}
+std::function<std::string(pkgCache::PkgIterator const &)> CandidateVersion(pkgCacheFile * const Cache)
+{
+ return std::bind(static_cast<std::string(*)(pkgCacheFile * const, pkgCache::PkgIterator const&)>(&CandidateVersion), Cache, std::placeholders::_1);
+}
+std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg)
+{
+ return std::string((*Cache)[Pkg].CurVersion) + " => " + (*Cache)[Pkg].CandVersion;
+}
+std::function<std::string(pkgCache::PkgIterator const &)> CurrentToCandidateVersion(pkgCacheFile * const Cache)
+{
+ return std::bind(static_cast<std::string(*)(pkgCacheFile * const, pkgCache::PkgIterator const&)>(&CurrentToCandidateVersion), Cache, std::placeholders::_1);
+}
+bool AlwaysTrue(pkgCache::PkgIterator const &)
+{
+ return true;
+}
+std::string EmptyString(pkgCache::PkgIterator const &)
+{
+ return std::string();
+}
+