summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMake/Translations.cmake1
-rw-r--r--apt-pkg/depcache.cc56
-rw-r--r--apt-pkg/depcache.h4
-rw-r--r--apt-pkg/init.cc2
-rw-r--r--apt-pkg/install-progress.cc12
-rw-r--r--apt-private/private-install.cc71
-rw-r--r--apt-private/private-output.cc16
-rw-r--r--doc/examples/configure-index3
-rw-r--r--test/libapt/install_progress_test.cc20
9 files changed, 173 insertions, 12 deletions
diff --git a/CMake/Translations.cmake b/CMake/Translations.cmake
index 24925105c..a7fe6c95b 100644
--- a/CMake/Translations.cmake
+++ b/CMake/Translations.cmake
@@ -16,6 +16,7 @@ function(apt_add_translation_domain)
set(domain ${NLS_DOMAIN})
set(xgettext_params
--add-comments
+ --from-code=utf-8
--foreign
--package-name=${PROJECT_NAME}
--package-version=${PACKAGE_VERSION}
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index e3e8d627c..76a5c09ba 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -42,6 +42,7 @@
#include <unordered_map>
#include <utility>
#include <vector>
+#include <dirent.h>
#include <sys/stat.h>
@@ -2613,3 +2614,58 @@ bool pkgDepCache::PhasingApplied(pkgCache::PkgIterator Pkg) const
return true;
}
/*}}}*/
+
+// DepCache::BootSize /*{{{*/
+double pkgDepCache::BootSize(bool initrdOnly)
+{
+ double BootSize = 0;
+ int BootCount = 0;
+ auto VirtualKernelPkg = FindPkg("$kernel", "any");
+ if (VirtualKernelPkg.end())
+ return 0;
+
+ for (pkgCache::PrvIterator Prv = VirtualKernelPkg.ProvidesList(); Prv.end() == false; ++Prv)
+ {
+ auto Pkg = Prv.OwnerPkg();
+ if ((*this)[Pkg].NewInstall())
+ BootSize += (*this)[Pkg].InstallVer->InstalledSize, BootCount++;
+ }
+ if (BootCount == 0)
+ return 0;
+ if (initrdOnly)
+ BootSize = 0;
+
+ DIR *boot = opendir(_config->FindDir("Dir::Boot").c_str());
+ struct dirent *ent;
+ if (boot)
+ {
+ double initrdSize = 0;
+ double mapSize = 0;
+ while ((ent = readdir(boot)))
+ {
+ enum
+ {
+ INITRD,
+ MAP
+ } type;
+ if (APT::String::Startswith(ent->d_name, "initrd.img-"))
+ type = INITRD;
+ else if (APT::String::Startswith(ent->d_name, "System.map-"))
+ type = MAP;
+ else
+ continue;
+
+ auto path = _config->FindDir("Dir::Boot") + ent->d_name;
+
+ if (struct stat st; stat(path.c_str(), &st) == 0)
+ {
+ double &targetSize = type == INITRD ? initrdSize : mapSize;
+ targetSize = std::max(targetSize, double(st.st_size));
+ }
+ }
+ closedir(boot);
+ return initrdSize ? BootSize + BootCount * (initrdSize + mapSize) * 1.1 : 0;
+ }
+ return 0;
+}
+ /*}}}*/
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
index 5dd022b56..23047b97a 100644
--- a/apt-pkg/depcache.h
+++ b/apt-pkg/depcache.h
@@ -490,7 +490,9 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace
virtual ~pkgDepCache();
bool CheckConsistency(char const *const msgtag = "");
-
+#ifdef APT_COMPILING_APT
+ double BootSize(bool initrdOnly);
+#endif
protected:
// methods call by IsInstallOk
bool IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg,
diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc
index 75935404f..487f94f20 100644
--- a/apt-pkg/init.cc
+++ b/apt-pkg/init.cc
@@ -147,6 +147,8 @@ bool pkgInitConfig(Configuration &Cnf)
// Configuration
Cnf.CndSet("Dir::Etc", &CONF_DIR[1]);
+ Cnf.CndSet("Dir::Boot", "boot");
+ Cnf.CndSet("Dir::Usr", "usr");
Cnf.CndSet("Dir::Etc::sourcelist","sources.list");
Cnf.CndSet("Dir::Etc::sourceparts","sources.list.d");
Cnf.CndSet("Dir::Etc::main","apt.conf");
diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc
index 2b0dc21ea..fe3324426 100644
--- a/apt-pkg/install-progress.cc
+++ b/apt-pkg/install-progress.cc
@@ -13,6 +13,7 @@
#include <sstream>
#include <vector>
#include <fcntl.h>
+#include <langinfo.h>
#include <sys/ioctl.h>
#include <unistd.h>
@@ -344,14 +345,23 @@ void PackageManagerFancy::Stop()
std::string
PackageManagerFancy::GetTextProgressStr(float Percent, int OutputSize)
{
+ bool Unicode = strcmp(nl_langinfo(CODESET), "UTF-8") == 0;
std::string output;
if (unlikely(OutputSize < 3))
return output;
int const BarSize = OutputSize - 2; // bar without the leading "[" and trailing "]"
int const BarDone = std::max(0, std::min(BarSize, static_cast<int>(std::floor(Percent * BarSize))));
+ double dummy;
+ double const BarDoneFractional = std::modf(Percent * BarSize, &dummy);
+ const char *const BarDoneFractionalChar = (const char *[]){
+ " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"}[static_cast<int>(std::floor(BarDoneFractional * 8))];
output.append("[");
- std::fill_n(std::fill_n(std::back_inserter(output), BarDone, '#'), BarSize - BarDone, '.');
+ for (int i = 0; i < BarDone; i++)
+ output.append(Unicode ? "█" : "#");
+ if (BarDone + 1 <= BarSize)
+ output.append(Unicode ? BarDoneFractionalChar : ".");
+ std::fill_n(std::back_inserter(output), BarSize - BarDone - 1, Unicode ? ' ' : '.');
output.append("]");
return output;
}
diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc
index 3efae0112..ecbd703d8 100644
--- a/apt-private/private-install.cc
+++ b/apt-private/private-install.cc
@@ -28,6 +28,8 @@
#include <map>
#include <set>
#include <vector>
+#include <langinfo.h>
+#include <sys/statvfs.h>
#include <apt-private/acqprogress.h>
#include <apt-private/private-cachefile.h>
@@ -322,7 +324,7 @@ 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,outVer < 30 ? _("Need to get %sB/%sB of archives.\n") : _(" Download size: %sB/%sB\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
@@ -333,10 +335,69 @@ bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, boo
// 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,outVer < 30 ? _("After this operation, %sB of additional disk space will be used.\n") : _(" Installed size: %sB\n"),
- SizeToStr(Cache->UsrSize()).c_str());
+ if (outVer < 30)
+ ioprintf(c1out, _("After this operation, %sB of additional disk space will be used.\n"),
+ SizeToStr(Cache->UsrSize()).c_str());
+ else
+ {
+ struct statvfs st;
+ if (statvfs(_config->FindDir("Dir::Usr").c_str(), &st) == 0)
+ {
+ struct statvfs st_boot;
+ double BootSize = 0;
+ double InitrdSize = 0;
+ if (statvfs(_config->FindDir("Dir::Boot").c_str(), &st_boot) == 0 && st_boot.f_fsid != st.f_fsid)
+ BootSize = Cache->BootSize(false);
+ else
+ InitrdSize = Cache->BootSize(true); /* initrd only, adding to /usr space */
+
+ ioprintf(c1out, " ");
+ // 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, _("Space needed: %sB / %sB available\n"),
+ SizeToStr(Cache->UsrSize() + InitrdSize).c_str(), SizeToStr((st.f_bsize * st.f_bavail)).c_str());
+
+ if (Cache->UsrSize() > 0 && static_cast<unsigned long long>(Cache->UsrSize()) > (st.f_bsize * st.f_bavail))
+ {
+ // 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
+ _error->Warning(_("More space needed than available: %sB > %sB, installation may fail"),
+ SizeToStr(Cache->UsrSize()).c_str(),
+ SizeToStr((st.f_bsize * st.f_bavail)).c_str());
+ }
+ if (BootSize != 0)
+ {
+ bool Unicode = strcmp(nl_langinfo(CODESET), "UTF-8") == 0;
+ ioprintf(c1out, Unicode ? " └─ " : " - ");
+ // 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 -
+ // The first %s is the location of the boot directory (determined from Dir::Boot),
+ // and it tells the space being needed there.
+ // (We have two spaces to align with parent "space needed:"for /boot)
+ ioprintf(c1out, _("in %s: %sB / %sB available\n"),
+ _config->FindFile("Dir::Boot").c_str(), SizeToStr(BootSize).c_str(), SizeToStr((st_boot.f_bsize * st_boot.f_bavail)).c_str());
+ if (BootSize > (st_boot.f_bsize * st_boot.f_bavail))
+ // 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
+ // The first %s is the location of the boot directory (determined from Dir::Boot)
+ _error->Warning(_("More space needed in %s than available: %sB > %sB, installation may fail"),
+ _config->FindFile("Dir::Boot").c_str(),
+ SizeToStr(BootSize).c_str(),
+ SizeToStr((st_boot.f_bsize * st_boot.f_bavail)).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, " ");
+ ioprintf(c1out, _("Space needed: %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
@@ -380,7 +441,9 @@ bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, boo
if (_config->FindI("quiet",0) < 2 &&
_config->FindB("APT::Get::Assume-Yes",false) == false)
{
- if (YnPrompt(outVer < 30 ? _("Do you want to continue?") : _("Continue?")) == false)
+ // YnPrompt shows all warnings before prompting, so ask stronger and default to N if we have any.
+ auto Default = outVer < 30 ? true : _error->empty();
+ if (not YnPrompt(outVer < 30 ? _("Do you want to continue?") : (Default ? _("Continue?") : _("Continue anyway?")), Default))
{
c2out << _("Abort.") << std::endl;
exit(1);
diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc
index f6df3f46c..95dc740cc 100644
--- a/apt-private/private-output.cc
+++ b/apt-private/private-output.cc
@@ -642,7 +642,7 @@ bool ShowDowngraded(ostream &out,CacheFile &Cache)
},
&PrettyFullName,
CurrentToCandidateVersion(&Cache),
- "APT::Color::Green");
+ "APT::Color::Yellow");
}
/*}}}*/
// ShowHold - Show held but changed packages /*{{{*/
@@ -758,9 +758,11 @@ void Stats(ostream &out, pkgDepCache &Dep, APT::PackageVector const &HeldBackPac
if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
ReInstall++;
}
- if (outVer >= 30)
- ioprintf(out, _("Summary:\n"));
- ioprintf(out,outVer < 30 ? _("%lu upgraded, %lu newly installed, ") : _(" Upgrading: %lu, Installing: %lu, "),
+ if (outVer >= 30) {
+ ioprintf(out, _("Summary:"));
+ ioprintf(out, "\n ");
+ }
+ ioprintf(out,outVer < 30 ? _("%lu upgraded, %lu newly installed, ") : _("Upgrading: %lu, Installing: %lu, "),
Upgrade,Install);
if (ReInstall != 0)
@@ -771,10 +773,12 @@ void Stats(ostream &out, pkgDepCache &Dep, APT::PackageVector const &HeldBackPac
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)
+ if (Dep.BadCount() != 0) {
+ if (outVer >= 30)
+ ioprintf(out, " ");
ioprintf(out,_("%lu not fully installed or removed.\n"),
Dep.BadCount());
+ }
}
/*}}}*/
// YnPrompt - Yes No Prompt. /*{{{*/
diff --git a/doc/examples/configure-index b/doc/examples/configure-index
index cc9a2e765..72e907507 100644
--- a/doc/examples/configure-index
+++ b/doc/examples/configure-index
@@ -487,6 +487,9 @@ Dir "<DIR>"
{
MountPath "/media/apt"; // Media AutoDetect mount path
};
+
+ Boot "<DIR>";
+ Usr "<DIR>";
};
// Things that effect the APT dselect method
diff --git a/test/libapt/install_progress_test.cc b/test/libapt/install_progress_test.cc
index 68101af9b..7015c619c 100644
--- a/test/libapt/install_progress_test.cc
+++ b/test/libapt/install_progress_test.cc
@@ -2,6 +2,7 @@
#include <apt-pkg/install-progress.h>
+#include <locale>
#include <string>
#include <gtest/gtest.h>
@@ -10,6 +11,7 @@ TEST(InstallProgressTest, FancyGetTextProgressStr)
{
APT::Progress::PackageManagerFancy p;
+ char *originalLocale = setlocale(LC_ALL, "C");
EXPECT_EQ(60u, p.GetTextProgressStr(0.5, 60).size());
EXPECT_EQ("[#.]", p.GetTextProgressStr(0.5, 4));
EXPECT_EQ("[..........]", p.GetTextProgressStr(0.0, 12));
@@ -22,4 +24,22 @@ TEST(InstallProgressTest, FancyGetTextProgressStr)
// deal with incorrect inputs gracefully (or should we die instead?)
EXPECT_EQ("[..........]", p.GetTextProgressStr(-1.0, 12));
EXPECT_EQ("[##########]", p.GetTextProgressStr(2.0, 12));
+
+ setlocale(LC_ALL, "C.UTF-8");
+
+ EXPECT_EQ("[█ ]", p.GetTextProgressStr(0.5, 4));
+ EXPECT_EQ("[ ]", p.GetTextProgressStr(0.0, 12));
+ EXPECT_EQ("[█ ]", p.GetTextProgressStr(0.1, 12));
+ EXPECT_EQ("[████ ]", p.GetTextProgressStr(0.4, 12));
+ EXPECT_EQ("[████▉ ]", p.GetTextProgressStr(0.4999, 12));
+ EXPECT_EQ("[█████ ]", p.GetTextProgressStr(0.5000, 12));
+ EXPECT_EQ("[█████ ]", p.GetTextProgressStr(0.5001, 12));
+ EXPECT_EQ("[█████████ ]", p.GetTextProgressStr(0.9001, 12));
+ EXPECT_EQ("[██████████]", p.GetTextProgressStr(1.0, 12));
+
+ // deal with incorrect inputs gracefully (or should we die instead?)
+ EXPECT_EQ("[ ]", p.GetTextProgressStr(-1.0, 12));
+ EXPECT_EQ("[██████████]", p.GetTextProgressStr(2.0, 12));
+
+ setlocale(LC_ALL, originalLocale);
}