diff --git a/src/libutil-tests/util.cc b/src/libutil-tests/util.cc index c48b97e8e..32114d9da 100644 --- a/src/libutil-tests/util.cc +++ b/src/libutil-tests/util.cc @@ -158,6 +158,7 @@ TEST(renderSize, misc) ASSERT_EQ(renderSize(972, true), " 0.9 KiB"); ASSERT_EQ(renderSize(973, true), " 1.0 KiB"); // FIXME: should round down ASSERT_EQ(renderSize(1024, true), " 1.0 KiB"); + ASSERT_EQ(renderSize(-1024, true), " -1.0 KiB"); ASSERT_EQ(renderSize(1024 * 1024, true), "1024.0 KiB"); ASSERT_EQ(renderSize(1100 * 1024, true), " 1.1 MiB"); ASSERT_EQ(renderSize(2ULL * 1024 * 1024 * 1024, true), " 2.0 GiB"); diff --git a/src/libutil/include/nix/util/util.hh b/src/libutil/include/nix/util/util.hh index 26f03938a..cb1c9694d 100644 --- a/src/libutil/include/nix/util/util.hh +++ b/src/libutil/include/nix/util/util.hh @@ -104,7 +104,7 @@ N string2IntWithUnitPrefix(std::string_view s) * GiB`. If `align` is set, the number will be right-justified by * padding with spaces on the left. */ -std::string renderSize(uint64_t value, bool align = false); +std::string renderSize(int64_t value, bool align = false); /** * Parse a string into a float. diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 383a904ad..69826070c 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -132,15 +132,16 @@ std::optional string2Float(const std::string_view s) template std::optional string2Float(const std::string_view s); template std::optional string2Float(const std::string_view s); -std::string renderSize(uint64_t value, bool align) +std::string renderSize(int64_t value, bool align) { static const std::array prefixes{{'K', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'}}; size_t power = 0; - double res = value; - while (res > 1024 && power < prefixes.size()) { + double abs_value = std::abs(value); + while (abs_value > 1024 && power < prefixes.size()) { ++power; - res /= 1024; + abs_value /= 1024; } + double res = (double) value / std::pow(1024.0, power); return fmt(align ? "%6.1f %ciB" : "%.1f %ciB", power == 0 ? res / 1024 : res, prefixes.at(power)); } diff --git a/src/nix/diff-closures.cc b/src/nix/diff-closures.cc index cbf842e5c..d36a21d74 100644 --- a/src/nix/diff-closures.cc +++ b/src/nix/diff-closures.cc @@ -107,8 +107,7 @@ void printClosureDiff( if (!removed.empty() || !added.empty()) items.push_back(fmt("%s → %s", showVersions(removed), showVersions(added))); if (showDelta) - items.push_back( - fmt("%s%+.1f KiB" ANSI_NORMAL, sizeDelta > 0 ? ANSI_RED : ANSI_GREEN, sizeDelta / 1024.0)); + items.push_back(fmt("%s%s" ANSI_NORMAL, sizeDelta > 0 ? ANSI_RED : ANSI_GREEN, renderSize(sizeDelta))); logger->cout("%s%s: %s", indent, name, concatStringsSep(", ", items)); } } diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc index fef3ae120..146b775e5 100644 --- a/src/nix/path-info.cc +++ b/src/nix/path-info.cc @@ -141,7 +141,7 @@ struct CmdPathInfo : StorePathsCommand, MixJSON void printSize(std::ostream & str, uint64_t value) { if (humanReadable) - str << fmt("\t%s", renderSize(value, true)); + str << fmt("\t%s", renderSize((int64_t) value, true)); else str << fmt("\t%11d", value); }