summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2024-04-12 18:16:23 +0000
committerJulian Andres Klode <jak@debian.org>2024-04-12 18:16:23 +0000
commitb8e77c400eaec5983772f50d3f728373b5981866 (patch)
treeae0ba3624bef3e1549e2bf0f555590eb98e6513b
parent81c65f7e86b8f16eaaa91d9c205a594b0ebde159 (diff)
parentf725565ae69a06d0ad5747881b6f54a19c0c1763 (diff)
Merge branch 'terse-ui' into 'main'
Introduce new output format for apt(8) See merge request apt-team/apt!337
-rw-r--r--apt-pkg/contrib/progress.cc11
-rw-r--r--apt-private/private-cmndline.cc8
-rw-r--r--apt-private/private-install.cc214
-rw-r--r--apt-private/private-output.cc153
-rw-r--r--apt-private/private-output.h46
-rw-r--r--completions/bash/apt2
-rw-r--r--doc/apt-get.8.xml6
-rw-r--r--doc/examples/configure-index3
-rw-r--r--test/integration/framework1
-rwxr-xr-xtest/integration/test-bug-470115-new-and-tighten-recommends2
-rwxr-xr-xtest/integration/test-ubuntu-bug-6149934
11 files changed, 307 insertions, 143 deletions
diff --git a/apt-pkg/contrib/progress.cc b/apt-pkg/contrib/progress.cc
index a2c4332ca..df068e43a 100644
--- a/apt-pkg/contrib/progress.cc
+++ b/apt-pkg/contrib/progress.cc
@@ -153,13 +153,15 @@ void OpTextProgress::Done()
{
if (NoUpdate == false && OldOp.empty() == false)
{
- char S[300];
+ char S[300] = {};
if (_error->PendingError() == true)
snprintf(S,sizeof(S),_("%c%s... Error!"),'\r',OldOp.c_str());
- else
+ else if (not _config->FindB("APT::Internal::OpProgress::EraseLines", true))
snprintf(S,sizeof(S),_("%c%s... Done"),'\r',OldOp.c_str());
Write(S);
- cout << endl;
+ // FIXME: apt-cdrom relies on this end of line being printed
+ if (_error->PendingError() || not _config->FindB("APT::Internal::OpProgress::EraseLines", true))
+ cout << endl;
OldOp = string();
}
@@ -200,7 +202,8 @@ void OpTextProgress::Update()
{
snprintf(S,sizeof(S),"\r%s",OldOp.c_str());
Write(S);
- cout << endl;
+ if (_config->FindB("APT::Internal::OpProgress::EraseLines", true))
+ cout << endl;
}
// Print the spinner. Absolute progress shows us a time progress.
diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc
index 79881d034..3d6816d57 100644
--- a/apt-private/private-cmndline.cc
+++ b/apt-private/private-cmndline.cc
@@ -184,7 +184,8 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
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);
+ addArg('V',"verbose-versions", "APT::Get::Show-Versions",0);
+ addArg(0, "list-columns", "APT::Get::List-Columns", 0);
addArg(0, "autoremove", "APT::Get::AutomaticRemove", 0);
addArg(0, "auto-remove", "APT::Get::AutomaticRemove", 0);
addArg(0, "reinstall", "APT::Get::ReInstall", 0);
@@ -480,10 +481,15 @@ static bool ShowCommonHelp(APT_CMD const Binary, CommandLine &CmdL, std::vector<
static void BinarySpecificConfiguration(char const * const Binary) /*{{{*/
{
std::string const binary = flNotDir(Binary);
+ if (binary == "apt-cdrom" || binary == "apt-config")
+ {
+ _config->CndSet("Binary::apt-cdrom::APT::Internal::OpProgress::EraseLines", false);
+ }
if (binary == "apt" || binary == "apt-config")
{
if (getenv("NO_COLOR") == nullptr)
_config->CndSet("Binary::apt::APT::Color", true);
+ _config->CndSet("Binary::apt::APT::Output-Version", 30);
_config->CndSet("Binary::apt::APT::Cache::Show::Version", 2);
_config->CndSet("Binary::apt::APT::Cache::AllVersions", false);
_config->CndSet("Binary::apt::APT::Cache::ShowVirtuals", true);
diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc
index 254d93436..3efae0112 100644
--- a/apt-private/private-install.cc
+++ b/apt-private/private-install.cc
@@ -139,8 +139,10 @@ struct WarnUsrMerge {
}
};
#endif
+static void ShowWeakDependencies(CacheFile &Cache);
bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, bool ShwKept, bool Ask, bool Safety, std::string const &Hook, CommandLine const &CmdL)
{
+ auto outVer = _config->FindI("APT::Output-Version");
#ifdef REQUIRE_MERGED_USR
WarnUsrMerge warnUsrMerge(Cache);
#endif
@@ -221,8 +223,13 @@ bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, boo
}
// Show all the various warning indicators
- ShowDel(c1out,Cache);
+ if (_config->FindI("APT::Output-Version") < 30)
+ ShowDel(c1out,Cache);
ShowNew(c1out,Cache);
+ if (_config->FindI("APT::Output-Version") >= 30)
+ ShowWeakDependencies(Cache);
+ if (_config->FindI("APT::Output-Version") >= 30 && _config->FindB("APT::Get::Show-Upgraded",true) == true)
+ ShowUpgraded(c1out,Cache);
if (ShwKept == true)
{
ShowPhasing(c1out, Cache, PhasingPackages);
@@ -231,10 +238,13 @@ bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, boo
_error->Notice("Some packages may have been kept back due to phasing.");
}
bool const Hold = not ShowHold(c1out,Cache);
- if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
+ if (_config->FindI("APT::Output-Version") < 30 && _config->FindB("APT::Get::Show-Upgraded",true) == true)
ShowUpgraded(c1out,Cache);
bool const Downgrade = !ShowDowngraded(c1out,Cache);
+ // Show removed packages last
+ if (_config->FindI("APT::Output-Version") >= 30)
+ ShowDel(c1out,Cache);
bool Essential = false;
if (_config->FindB("APT::Get::Download-Only",false) == false)
Essential = !ShowEssential(c1out,Cache);
@@ -312,12 +322,12 @@ bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, boo
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"),
+ ioprintf(c1out,outVer < 30 ? _("Need to get %sB/%sB of archives.\n") : _(" Download size: %sB/%sB\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"),
+ ioprintf(c1out,outVer < 30 ? _("Need to get %sB of archives.\n") : _(" Download size: %sB\n"),
SizeToStr(DebBytes).c_str());
}
@@ -325,14 +335,16 @@ bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, boo
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"),
+ ioprintf(c1out,outVer < 30 ? _("After this operation, %sB of additional disk space will be used.\n") : _(" Installed size: %sB\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"),
+ ioprintf(c1out,outVer < 30 ? _("After this operation, %sB disk space will be freed.\n") : _(" Freed space: %sB\n"),
SizeToStr(-1*Cache->UsrSize()).c_str());
+ if (outVer >= 30)
+ ioprintf(c1out,"\n");
if (DownloadAllowed)
if (CheckFreeSpaceBeforeDownload(_config->FindDir("Dir::Cache::Archives"), (FetchBytes - FetchPBytes)) == false)
return false;
@@ -368,7 +380,7 @@ bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, boo
if (_config->FindI("quiet",0) < 2 &&
_config->FindB("APT::Get::Assume-Yes",false) == false)
{
- if (YnPrompt(_("Do you want to continue?")) == false)
+ if (YnPrompt(outVer < 30 ? _("Do you want to continue?") : _("Continue?")) == false)
{
c2out << _("Abort.") << std::endl;
exit(1);
@@ -903,6 +915,99 @@ struct PkgIsExtraInstalled {
return std::find(verset->begin(), verset->end(), Cand) == verset->end();
}
};
+/* Print out a list of suggested and recommended packages */
+static void ShowWeakDependencies(CacheFile &Cache)
+{
+ std::list<std::string> Recommends, Suggests, SingleRecommends, SingleSuggests;
+ SortedPackageUniverse Universe(Cache);
+ for (auto const &Pkg: Universe)
+ {
+ /* Just look at the ones we want to install */
+ if ((*Cache)[Pkg].NewInstall() == 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
+ if (Start->Type != pkgCache::Dep::Recommends && Start->Type != pkgCache::Dep::Suggests)
+ continue;
+
+ {
+ // Skip if we already saw this
+ std::string target;
+ for (pkgCache::DepIterator I = Start; I != D; ++I)
+ {
+ if (target.empty() == false)
+ target.append(" | ");
+ target.append(I.TargetPkg().FullName(true));
+ }
+ std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? SingleRecommends : SingleSuggests;
+ if (std::find(Type.begin(), Type.end(), target) != Type.end())
+ continue;
+ Type.push_back(target);
+ }
+
+ std::list<std::string> OrList;
+ bool foundInstalledInOrGroup = false;
+ for (pkgCache::DepIterator I = Start; I != D; ++I)
+ {
+ {
+ // satisfying package is installed and not marked for deletion
+ APT::VersionList installed = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::INSTALLED);
+ if (std::find_if(installed.begin(), installed.end(),
+ [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Delete() == false; }) != installed.end())
+ {
+ foundInstalledInOrGroup = true;
+ break;
+ }
+ }
+
+ {
+ // satisfying package is upgraded to/new install
+ APT::VersionList upgrades = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::CANDIDATE);
+ if (std::find_if(upgrades.begin(), upgrades.end(),
+ [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Upgrade(); }) != upgrades.end())
+ {
+ foundInstalledInOrGroup = true;
+ break;
+ }
+ }
+
+ if (OrList.empty())
+ OrList.push_back(I.TargetPkg().FullName(true));
+ else
+ OrList.push_back("| " + I.TargetPkg().FullName(true));
+ }
+
+ if(foundInstalledInOrGroup == false)
+ {
+ std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? Recommends : Suggests;
+ std::move(OrList.begin(), OrList.end(), std::back_inserter(Type));
+ }
+ }
+ }
+ auto always_true = [](std::string const&) { return true; };
+ auto string_ident = [](std::string const&str) { return str; };
+ auto verbose_show_candidate =
+ [&Cache](std::string str)
+ {
+ if (APT::String::Startswith(str, "| "))
+ str.erase(0, 2);
+ pkgCache::PkgIterator const Pkg = Cache->FindPkg(str);
+ if (Pkg.end() == true)
+ return "";
+ return (*Cache)[Pkg].CandVersion;
+ };
+ ShowList(c1out,_("Suggested packages:"), Suggests,
+ always_true, string_ident, verbose_show_candidate);
+ ShowList(c1out,_("Recommended packages:"), Recommends,
+ always_true, string_ident, verbose_show_candidate);
+}
+
bool DoInstall(CommandLine &CmdL)
{
CacheFile Cache;
@@ -933,101 +1038,14 @@ bool DoInstall(CommandLine &CmdL)
/* Print out a list of packages that are going to be installed extra
to what the user asked */
SortedPackageUniverse Universe(Cache);
- if (Cache->InstCount() != verset[MOD_INSTALL].size())
+ if (_config->FindI("APT::Output-Version") < 30 && Cache->InstCount() != verset[MOD_INSTALL].size())
ShowList(c1out, _("The following additional packages will be installed:"), Universe,
PkgIsExtraInstalled(&Cache, &verset[MOD_INSTALL]),
- &PrettyFullName, CandidateVersion(&Cache));
+ &PrettyFullName, CandidateVersion(&Cache), "APT::Color::Green");
/* Print out a list of suggested and recommended packages */
- {
- std::list<std::string> Recommends, Suggests, SingleRecommends, SingleSuggests;
- for (auto const &Pkg: Universe)
- {
- /* 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
- if (Start->Type != pkgCache::Dep::Recommends && Start->Type != pkgCache::Dep::Suggests)
- continue;
-
- {
- // Skip if we already saw this
- std::string target;
- for (pkgCache::DepIterator I = Start; I != D; ++I)
- {
- if (target.empty() == false)
- target.append(" | ");
- target.append(I.TargetPkg().FullName(true));
- }
- std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? SingleRecommends : SingleSuggests;
- if (std::find(Type.begin(), Type.end(), target) != Type.end())
- continue;
- Type.push_back(target);
- }
-
- std::list<std::string> OrList;
- bool foundInstalledInOrGroup = false;
- for (pkgCache::DepIterator I = Start; I != D; ++I)
- {
- {
- // satisfying package is installed and not marked for deletion
- APT::VersionList installed = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::INSTALLED);
- if (std::find_if(installed.begin(), installed.end(),
- [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Delete() == false; }) != installed.end())
- {
- foundInstalledInOrGroup = true;
- break;
- }
- }
-
- {
- // satisfying package is upgraded to/new install
- APT::VersionList upgrades = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::CANDIDATE);
- if (std::find_if(upgrades.begin(), upgrades.end(),
- [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Upgrade(); }) != upgrades.end())
- {
- foundInstalledInOrGroup = true;
- break;
- }
- }
-
- if (OrList.empty())
- OrList.push_back(I.TargetPkg().FullName(true));
- else
- OrList.push_back("| " + I.TargetPkg().FullName(true));
- }
-
- if(foundInstalledInOrGroup == false)
- {
- std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? Recommends : Suggests;
- std::move(OrList.begin(), OrList.end(), std::back_inserter(Type));
- }
- }
- }
- auto always_true = [](std::string const&) { return true; };
- auto string_ident = [](std::string const&str) { return str; };
- auto verbose_show_candidate =
- [&Cache](std::string str)
- {
- if (APT::String::Startswith(str, "| "))
- str.erase(0, 2);
- pkgCache::PkgIterator const Pkg = Cache->FindPkg(str);
- if (Pkg.end() == true)
- return "";
- return (*Cache)[Pkg].CandVersion;
- };
- ShowList(c1out,_("Suggested packages:"), Suggests,
- always_true, string_ident, verbose_show_candidate);
- ShowList(c1out,_("Recommended packages:"), Recommends,
- always_true, string_ident, verbose_show_candidate);
- }
+ if (_config->FindI("APT::Output-Version") < 30)
+ ShowWeakDependencies(Cache);
RunJsonHook("AptCli::Hooks::Install", "org.debian.apt.hooks.install.pre-prompt", CmdL.FileList, Cache);
diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc
index 93b942458..bbf50397f 100644
--- a/apt-private/private-output.cc
+++ b/apt-private/private-output.cc
@@ -316,6 +316,83 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/
out << output;
}
/*}}}*/
+// ShowWithColumns - Show a list in the style of ls /*{{{*/
+// ---------------------------------------------------------------------
+/* This prints out a vector of strings with the given indent and in as
+ many columns as will fit the screen width.
+
+ The output looks like:
+ abiword debootstrap gir1.2-upowerglib-1.0
+ abiword-common dh-make google-chrome-beta
+ abiword-plugin-grammar dmeventd gstreamer1.0-clutter-3.0
+ binfmt-support dmsetup hostname
+ console-setup evolution-data-server iproute2
+ console-setup-linux evolution-data-server-common
+ coreutils ffmpeg
+ */
+struct columnInfo
+{
+ bool ValidLen;
+ size_t LineWidth;
+ vector<size_t> RemainingWidths;
+};
+void ShowWithColumns(ostream &out, vector<string> const &List, size_t Indent, size_t ScreenWidth)
+{
+ constexpr size_t MinColumnWidth = 2;
+ constexpr size_t ColumnSpace = 1;
+
+ size_t const ListSize = List.size();
+ size_t const MaxScreenCols = (ScreenWidth - Indent) /
+ MinColumnWidth;
+ size_t const MaxNumCols = min(MaxScreenCols, ListSize);
+
+ vector<columnInfo> ColumnInfo(MaxNumCols);
+ for (size_t I = 0; I < MaxNumCols; ++I) {
+ ColumnInfo[I].ValidLen = true;
+ ColumnInfo[I].LineWidth = (I + 1) * MinColumnWidth;
+ ColumnInfo[I].RemainingWidths.resize(I + 1, MinColumnWidth);
+ }
+
+ for (size_t I = 0; I < ListSize; ++I) {
+ for (size_t J = 0; J < MaxNumCols; ++J) {
+ auto& Col = ColumnInfo[J];
+ if (!Col.ValidLen)
+ continue;
+
+ size_t Idx = I / ((ListSize + J) / (J + 1));
+ size_t RealColLen = List[I].size() + (Idx == J ? 0 : ColumnSpace);
+ if (Col.RemainingWidths[Idx] < RealColLen) {
+ Col.LineWidth += RealColLen - Col.RemainingWidths[Idx];
+ Col.RemainingWidths[Idx] = RealColLen;
+ Col.ValidLen = Col.LineWidth < ScreenWidth;
+ }
+ }
+ }
+ size_t NumCols = MaxNumCols;
+ while (NumCols > 1 && !ColumnInfo[NumCols - 1].ValidLen)
+ --NumCols;
+
+ size_t NumRows = ListSize / NumCols + (ListSize % NumCols != 0);
+ auto const &LineFormat = ColumnInfo[NumCols - 1];
+ for (size_t Row = 0; Row < NumRows; ++Row) {
+ size_t Col = 0;
+ size_t I = Row;
+ out << string(Indent, ' ');
+ while (true) {
+ out << List[I];
+
+ size_t CurLen = List[I].size();
+ size_t MaxLen = LineFormat.RemainingWidths[Col++];
+ I += NumRows;
+ if (I >= ListSize)
+ break;
+
+ out << string(MaxLen - CurLen, ' ');
+ }
+ out << endl;
+ }
+}
+ /*}}}*/
// ShowBroken - Debugging aide /*{{{*/
// ---------------------------------------------------------------------
/* This prints out the names of all the packages that are broken along
@@ -447,8 +524,10 @@ void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
{
if (Cache->BrokenCount() == 0)
return;
-
- out << _("The following packages have unmet dependencies:") << endl;
+ if (_config->FindI("APT::Output-Version") < 30)
+ out << _("The following packages have unmet dependencies:") << endl;
+ else
+ out << _("Unsatisfied dependencies:") << endl;
SortedPackageUniverse Universe(Cache);
for (auto const &Pkg: Universe)
ShowBrokenPackage(out, &Cache, Pkg, Now);
@@ -458,7 +537,10 @@ void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
if (Cache->BrokenCount() == 0)
return;
- out << _("The following packages have unmet dependencies:") << endl;
+ if (_config->FindI("APT::Output-Version") < 30)
+ out << _("The following packages have unmet dependencies:") << endl;
+ else
+ out << _("Unsatisfied dependencies:") << endl;
APT::PackageUniverse Universe(Cache);
for (auto const &Pkg: Universe)
ShowBrokenPackage(out, &Cache, Pkg, Now);
@@ -468,17 +550,33 @@ void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
void ShowNew(ostream &out,CacheFile &Cache)
{
SortedPackageUniverse Universe(Cache);
- ShowList(out,_("The following NEW packages will be installed:"), Universe,
- [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); },
+ if (_config->FindI("APT::Output-Version") < 30) {
+ ShowList(out,_("The following NEW packages will be installed:"), Universe,
+ [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); },
+ &PrettyFullName,
+ CandidateVersion(&Cache),
+ "APT::Color::Green");
+ return;
+ }
+
+ ShowList(out,_("Installing:"), Universe,
+ [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall() && (Cache[Pkg].Flags & pkgCache::Flag::Auto) == 0; },
+ &PrettyFullName,
+ CandidateVersion(&Cache),
+ "APT::Color::Green");
+ ShowList(out,_("Installing dependencies:"), Universe,
+ [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall() && Cache[Pkg].Flags & pkgCache::Flag::Auto;},
&PrettyFullName,
- CandidateVersion(&Cache));
+ CandidateVersion(&Cache),
+ "APT::Color::Green");
}
/*}}}*/
// ShowDel - Show packages to delete /*{{{*/
void ShowDel(ostream &out,CacheFile &Cache)
{
SortedPackageUniverse Universe(Cache);
- ShowList(out,_("The following packages will be REMOVED:"), Universe,
+ auto title = _config->FindI("APT::Output-Version") < 30 ? _("The following packages will be REMOVED:") : _("REMOVING:");
+ ShowList(out,title, Universe,
[&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].Delete(); },
[&Cache](pkgCache::PkgIterator const &Pkg)
{
@@ -487,14 +585,18 @@ void ShowDel(ostream &out,CacheFile &Cache)
str.append("*");
return str;
},
- CandidateVersion(&Cache));
+ CandidateVersion(&Cache),
+ "APT::Color::Red");
}
/*}}}*/
// ShowPhasing - Show packages kept due to phasing /*{{{*/
void ShowPhasing(ostream &out, CacheFile &Cache, APT::PackageVector const &HeldBackPackages)
{
SortedPackageUniverse Universe(Cache);
- ShowList(out, _("The following upgrades have been deferred due to phasing:"), HeldBackPackages,
+ auto title = _config->FindI("APT::Output-Version") < 30
+ ? _("The following upgrades have been deferred due to phasing:")
+ : _("Not upgrading yet due to phasing:");
+ ShowList(out, title, HeldBackPackages,
&AlwaysTrue,
&PrettyFullName,
CurrentToCandidateVersion(&Cache));
@@ -504,7 +606,8 @@ void ShowPhasing(ostream &out, CacheFile &Cache, APT::PackageVector const &HeldB
void ShowKept(ostream &out,CacheFile &Cache, APT::PackageVector const &HeldBackPackages)
{
SortedPackageUniverse Universe(Cache);
- ShowList(out,_("The following packages have been kept back:"), HeldBackPackages,
+ auto title = _config->FindI("APT::Output-Version") < 30 ? _("The following packages have been kept back:") : _("Not upgrading:");
+ ShowList(out, title, HeldBackPackages,
&AlwaysTrue,
&PrettyFullName,
CurrentToCandidateVersion(&Cache));
@@ -514,13 +617,15 @@ void ShowKept(ostream &out,CacheFile &Cache, APT::PackageVector const &HeldBackP
void ShowUpgraded(ostream &out,CacheFile &Cache)
{
SortedPackageUniverse Universe(Cache);
- ShowList(out,_("The following packages will be upgraded:"), Universe,
+ auto title = _config->FindI("APT::Output-Version") < 30 ? _("The following packages will be upgraded:") : _("Upgrading:");
+ ShowList(out, title, Universe,
[&Cache](pkgCache::PkgIterator const &Pkg)
{
return Cache[Pkg].Upgrade() == true && Cache[Pkg].NewInstall() == false;
},
&PrettyFullName,
- CurrentToCandidateVersion(&Cache));
+ CurrentToCandidateVersion(&Cache),
+ "APT::Color::Green");
}
/*}}}*/
// ShowDowngraded - Show downgraded packages /*{{{*/
@@ -529,20 +634,23 @@ void ShowUpgraded(ostream &out,CacheFile &Cache)
bool ShowDowngraded(ostream &out,CacheFile &Cache)
{
SortedPackageUniverse Universe(Cache);
- return ShowList(out,_("The following packages will be DOWNGRADED:"), Universe,
+ auto title = _config->FindI("APT::Output-Version") < 30 ? _("The following packages will be DOWNGRADED:") : _("DOWNGRADING:");
+ return ShowList(out, title, Universe,
[&Cache](pkgCache::PkgIterator const &Pkg)
{
return Cache[Pkg].Downgrade() == true && Cache[Pkg].NewInstall() == false;
},
&PrettyFullName,
- CurrentToCandidateVersion(&Cache));
+ CurrentToCandidateVersion(&Cache),
+ "APT::Color::Green");
}
/*}}}*/
// ShowHold - Show held but changed packages /*{{{*/
bool ShowHold(ostream &out,CacheFile &Cache)
{
SortedPackageUniverse Universe(Cache);
- return ShowList(out,_("The following held packages will be changed:"), Universe,
+ auto title = _config->FindI("APT::Output-Version") < 30 ? _("The following held packages will be changed:") : _("Changing held packages:Changing held packages:");
+ return ShowList(out, title, Universe,
[&Cache](pkgCache::PkgIterator const &Pkg)
{
return Pkg->SelectedState == pkgCache::State::Hold &&
@@ -633,6 +741,7 @@ void Stats(ostream &out, pkgDepCache &Dep, APT::PackageVector const &HeldBackPac
unsigned long Downgrade = 0;
unsigned long Install = 0;
unsigned long ReInstall = 0;
+ auto outVer = _config->FindI("APT::Output-Version");
for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I)
{
if (Dep[I].NewInstall() == true)
@@ -649,18 +758,20 @@ void Stats(ostream &out, pkgDepCache &Dep, APT::PackageVector const &HeldBackPac
if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
ReInstall++;
}
-
- ioprintf(out,_("%lu upgraded, %lu newly installed, "),
+ if (outVer >= 30)
+ ioprintf(out, _("Summary:\n"));
+ ioprintf(out,outVer < 30 ? _("%lu upgraded, %lu newly installed, ") : _(" Upgrading: %lu, Installing: %lu, "),
Upgrade,Install);
if (ReInstall != 0)
- ioprintf(out,_("%lu reinstalled, "),ReInstall);
+ ioprintf(out,outVer < 30 ? _("%lu reinstalled, ") : _("Reinstalling: %lu, "),ReInstall);
if (Downgrade != 0)
- ioprintf(out,_("%lu downgraded, "),Downgrade);
+ ioprintf(out,outVer < 30 ? _("%lu downgraded, ") : _("Downgrading: %lu, "),Downgrade);
- ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
+ ioprintf(out, outVer < 30 ? _("%lu to remove and %lu not upgraded.\n") : _("Removing: %lu, Not Upgrading: %lu\n"),
Dep.DelCount(), HeldBackPackages.size());
-
+
+ // FIXME: outVer
if (Dep.BadCount() != 0)
ioprintf(out,_("%lu not fully installed or removed.\n"),
Dep.BadCount());
diff --git a/apt-private/private-output.h b/apt-private/private-output.h
index c3e73d592..4cc7c01b4 100644
--- a/apt-private/private-output.h
+++ b/apt-private/private-output.h
@@ -10,6 +10,7 @@
#include <functional>
#include <iostream>
#include <string>
+#include <vector>
// forward declaration
class pkgCacheFile;
@@ -35,16 +36,24 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,
APT_PUBLIC void ShowBroken(std::ostream &out, CacheFile &Cache, bool const Now);
APT_PUBLIC void ShowBroken(std::ostream &out, pkgCacheFile &Cache, bool const Now);
+APT_PUBLIC void ShowWithColumns(std::ostream &out, const std::vector<std::string> &List, size_t Indent, size_t ScreenWidth);
+
template<class Container, class PredicateC, class DisplayP, class DisplayV> bool ShowList(std::ostream &out, std::string const &Title,
Container const &cont,
PredicateC Predicate,
DisplayP PkgDisplay,
- DisplayV VerboseDisplay)
+ DisplayV VerboseDisplay,
+ std::string colorName = "APT::Color::Neutral")
{
size_t const ScreenWidth = (::ScreenWidth > 3) ? ::ScreenWidth - 3 : 0;
int ScreenUsed = 0;
bool const ShowVersions = _config->FindB("APT::Get::Show-Versions", false);
+ bool const ListColumns = _config->FindB("APT::Get::List-Columns", _config->FindI("APT::Output-Version") >= 30);
bool printedTitle = false;
+ std::vector<std::string> PackageList;
+
+ auto setColor = _config->FindI("APT::Output-Version") >= 30 ? _config->Find(colorName) : "";
+ auto resetColor = _config->FindI("APT::Output-Version") >= 30 ? _config->Find("APT::Color::Neutral") : "";
for (auto const &Pkg: cont)
{
@@ -59,7 +68,7 @@ template<class Container, class PredicateC, class DisplayP, class DisplayV> bool
if (ShowVersions == true)
{
- out << std::endl << " " << PkgDisplay(Pkg);
+ out << std::endl << " " << setColor << PkgDisplay(Pkg) << resetColor;
std::string const verbose = VerboseDisplay(Pkg);
if (verbose.empty() == false)
out << " (" << verbose << ")";
@@ -67,24 +76,37 @@ template<class Container, class PredicateC, class DisplayP, class DisplayV> bool
else
{
std::string const PkgName = PkgDisplay(Pkg);
- if (ScreenUsed == 0 || (ScreenUsed + PkgName.length()) >= ScreenWidth)
+ if (ListColumns)
+ PackageList.push_back(PkgName);
+ else
{
- out << std::endl << " ";
- ScreenUsed = 0;
+ if (ScreenUsed == 0 || (ScreenUsed + PkgName.length()) >= ScreenWidth)
+ {
+ out << std::endl
+ << " ";
+ ScreenUsed = 0;
+ }
+ else if (ScreenUsed != 0)
+ {
+ out << " ";
+ ++ScreenUsed;
+ }
+ out << setColor << PkgName << resetColor;
+ ScreenUsed += PkgName.length();
}
- else if (ScreenUsed != 0)
- {
- out << " ";
- ++ScreenUsed;
- }
- out << PkgName;
- ScreenUsed += PkgName.length();
}
}
if (printedTitle == true)
{
out << std::endl;
+ if (ListColumns && not PackageList.empty()) {
+ out << setColor;
+ ShowWithColumns(out, PackageList, 2, ScreenWidth);
+ out << resetColor;
+ }
+ if (_config->FindI("APT::Output-Version") >= 30)
+ out << std::endl;
return false;
}
return true;
diff --git a/completions/bash/apt b/completions/bash/apt
index 59a8eaa94..7c4b44a1a 100644
--- a/completions/bash/apt
+++ b/completions/bash/apt
@@ -73,7 +73,7 @@ _apt()
case ${command-} in
install|reinstall|remove|purge|upgrade|dist-upgrade|full-upgrade|autoremove|autopurge)
COMPREPLY=( $( compgen -W '--show-progress
- --fix-broken --purge --verbose-versions --auto-remove
+ --fix-broken --purge --verbose-versions --no-list-columns --auto-remove
-s --simulate --dry-run
--download
--fix-missing
diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml
index da1e91997..807345a3d 100644
--- a/doc/apt-get.8.xml
+++ b/doc/apt-get.8.xml
@@ -410,6 +410,12 @@
Configuration Item: <literal>APT::Get::Show-Versions</literal>.</para></listitem>
</varlistentry>
+ <varlistentry><term><option>--no-list-columns</option></term>
+ <listitem><para>Display package lists without arranging them in columns. By
+ default, package lists are printed in the style of the "ls" command.
+ Configuration Item: <literal>APT::Get::List-Columns</literal>.</para></listitem>
+ </varlistentry>
+
<varlistentry><term><option>-a</option></term>
<term><option>--host-architecture</option></term>
<listitem><para>This option controls the architecture packages are built for
diff --git a/doc/examples/configure-index b/doc/examples/configure-index
index da4998b4d..cc9a2e765 100644
--- a/doc/examples/configure-index
+++ b/doc/examples/configure-index
@@ -104,6 +104,7 @@ APT
Show-Upgraded "<BOOL>";
Show-Versions "<BOOL>";
+ List-Columns "<BOOL>";
Upgrade "<BOOL>";
Only-Upgrade "<BOOL>";
Upgrade-Allow-New "<BOOL>";
@@ -722,6 +723,7 @@ apt::system "<STRING>";
apt::acquire::translation "<STRING>"; // deprecated in favor of Acquire::Languages
apt::color::highlight "<STRING>";
apt::color::neutral "<STRING>";
+apt::output-version "<INT>";
dpkgpm::reporting-steps "<INT>";
@@ -880,6 +882,7 @@ Rred::f "<BOOL>";
Rred::Compress "<STRING>";
APT::Internal::OpProgress::Absolute "<BOOL>";
+APT::Internal::OpProgress::EraseLines "<BOOL>";
APT::Color "<BOOL>";
update-manager::always-include-phased-updates "<BOOL>";
diff --git a/test/integration/framework b/test/integration/framework
index 0570d5c8e..147de9808 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -444,6 +444,7 @@ _setupprojectenvironment() {
echo "Dir::Etc \"etc/apt\";" >> aptconfig.conf
echo "Dir::Log \"var/log/apt\";" >> aptconfig.conf
echo "APT::Get::Show-User-Simulation-Note \"false\";" >> aptconfig.conf
+ echo "Binary::apt::APT::Output-Version \"0\";" >> aptconfig.conf
echo "Dir::Bin::Methods \"${TMPWORKINGDIRECTORY}/rootdir/usr/lib/apt/methods\";" >> aptconfig.conf
# either store apt-key were we can access it, even if we run it as a different user
#cp "${APTCMDLINEBINDIR}/apt-key" "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/"
diff --git a/test/integration/test-bug-470115-new-and-tighten-recommends b/test/integration/test-bug-470115-new-and-tighten-recommends
index f27990e3e..e1c272b18 100755
--- a/test/integration/test-bug-470115-new-and-tighten-recommends
+++ b/test/integration/test-bug-470115-new-and-tighten-recommends
@@ -165,8 +165,6 @@ Conf upgrade-over-new (2 unstable [all])' aptget install upgrade-over-new -s
# the user doesn't seem to need it so avoid upgrading it
testsuccessequal 'Reading package lists...
Building dependency tree...
-Recommended packages:
- cool
The following packages will be upgraded:
now-satisfiable
1 upgraded, 0 newly installed, 0 to remove and 12 not upgraded.
diff --git a/test/integration/test-ubuntu-bug-614993 b/test/integration/test-ubuntu-bug-614993
index 542e55105..fe830b499 100755
--- a/test/integration/test-ubuntu-bug-614993
+++ b/test/integration/test-ubuntu-bug-614993
@@ -28,10 +28,6 @@ The following additional packages will be installed:
xserver-xorg-video-sisusb xserver-xorg-video-tdfx xserver-xorg-video-trident
xserver-xorg-video-tseng xserver-xorg-video-vesa xserver-xorg-video-vmware
xserver-xorg-video-voodoo
-Suggested packages:
- xfonts-scalable gpointing-device-settings touchfreeze firmware-linux
-Recommended packages:
- xauth intel-gpu-tools
The following packages will be REMOVED:
xserver-xorg-video-v4l
The following NEW packages will be installed: