From 62e80f889cb855a92d2aa1f90881c72d429a602c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 6 Nov 2025 13:06:08 +0100 Subject: [PATCH 1/2] Don't crash on flakerefs containing newlines Fixes #14311. (cherry picked from commit c1317017e902f34631f2f4598710114d36e84ee4) --- src/libflake/flakeref.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libflake/flakeref.cc b/src/libflake/flakeref.cc index 9a75a2259..503b6d512 100644 --- a/src/libflake/flakeref.cc +++ b/src/libflake/flakeref.cc @@ -80,7 +80,8 @@ std::pair parsePathFlakeRefWithFragment( std::smatch match; auto succeeds = std::regex_match(url, match, pathFlakeRegex); - assert(succeeds); + if (!succeeds) + throw Error("invalid flakeref '%s'", url); auto path = match[1].str(); auto query = decodeQuery(match[3]); auto fragment = percentDecode(match[5].str()); From a6fb25f9f4b3fe1f1321c6ecdeee61b261231c46 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 6 Nov 2025 22:12:56 +0100 Subject: [PATCH 2/2] Revert "Merge pull request #14380 from NixOS/backport-14364-to-2.30-maintenance" This reverts commit b479a25292e62b5f8baa4fdbf49aa07a63b16d8c, reversing changes made to fc0601b153eae43cee96c13c5d0b79282b8af184. --- src/libfetchers/git-utils.cc | 5 ++--- src/libmain/include/nix/main/shared.hh | 2 ++ src/libmain/shared.cc | 16 +++++++--------- src/libstore/gc.cc | 5 +++-- src/libstore/optimise-store.cc | 2 +- src/libutil-tests/util.cc | 1 - src/libutil/include/nix/util/util.hh | 4 +++- src/libutil/util.cc | 14 +++++++++----- src/nix/diff-closures.cc | 3 ++- src/nix/path-info.cc | 2 +- 10 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 7634f9da1..ce54f5747 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -8,7 +8,6 @@ #include "nix/util/users.hh" #include "nix/util/fs-sink.hh" #include "nix/util/sync.hh" -#include "nix/util/util.hh" #include #include @@ -518,12 +517,12 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this auto act = (Activity *) payload; act->result( resFetchStatus, - fmt("%d/%d objects received, %d/%d deltas indexed, %s", + fmt("%d/%d objects received, %d/%d deltas indexed, %.1f MiB", stats->received_objects, stats->total_objects, stats->indexed_deltas, stats->total_deltas, - renderSize(stats->received_bytes))); + stats->received_bytes / (1024.0 * 1024.0))); return getInterrupted() ? -1 : 0; } diff --git a/src/libmain/include/nix/main/shared.hh b/src/libmain/include/nix/main/shared.hh index 43069ba82..47d08a050 100644 --- a/src/libmain/include/nix/main/shared.hh +++ b/src/libmain/include/nix/main/shared.hh @@ -89,6 +89,8 @@ extern volatile ::sig_atomic_t blockInt; /* GC helpers. */ +std::string showBytes(uint64_t bytes); + struct GCResults; struct PrintFreed diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 9e25e5bf1..7187e9720 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -6,7 +6,6 @@ #include "nix/main/loggers.hh" #include "nix/main/progress-bar.hh" #include "nix/util/signals.hh" -#include "nix/util/util.hh" #include #include @@ -65,19 +64,18 @@ void printMissing(ref store, const MissingPaths & missing, Verbosity lvl) } if (!missing.willSubstitute.empty()) { + const float downloadSizeMiB = missing.downloadSize / (1024.f * 1024.f); + const float narSizeMiB = missing.narSize / (1024.f * 1024.f); if (missing.willSubstitute.size() == 1) { printMsg( - lvl, - "this path will be fetched (%s download, %s unpacked):", - renderSize(missing.downloadSize), - renderSize(missing.narSize)); + lvl, "this path will be fetched (%.2f MiB download, %.2f MiB unpacked):", downloadSizeMiB, narSizeMiB); } else { printMsg( lvl, - "these %d paths will be fetched (%s download, %s unpacked):", + "these %d paths will be fetched (%.2f MiB download, %.2f MiB unpacked):", missing.willSubstitute.size(), - renderSize(missing.downloadSize), - renderSize(missing.narSize)); + downloadSizeMiB, + narSizeMiB); } std::vector willSubstituteSorted = {}; std::for_each(missing.willSubstitute.begin(), missing.willSubstitute.end(), [&](const StorePath & p) { @@ -413,7 +411,7 @@ RunPager::~RunPager() PrintFreed::~PrintFreed() { if (show) - std::cout << fmt("%d store paths deleted, %s freed\n", results.paths.size(), renderSize(results.bytesFreed)); + std::cout << fmt("%d store paths deleted, %s freed\n", results.paths.size(), showBytes(results.bytesFreed)); } } // namespace nix diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 65662a1b8..2ab15639a 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -4,7 +4,6 @@ #include "nix/util/finally.hh" #include "nix/util/unix-domain-socket.hh" #include "nix/util/signals.hh" -#include "nix/util/util.hh" #include "nix/store/posix-fs-canonicalise.hh" #include "store-config-private.hh" @@ -905,7 +904,9 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) #endif ; - printInfo("note: currently hard linking saves %s", renderSize(unsharedSize - actualSize - overhead)); + printInfo( + "note: currently hard linking saves %.2f MiB", + ((unsharedSize - actualSize - overhead) / (1024.0 * 1024.0))); } /* While we're at it, vacuum the database. */ diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 3733a49a8..8073ee41b 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -312,7 +312,7 @@ void LocalStore::optimiseStore() optimiseStore(stats); - printInfo("%s freed by hard-linking %d files", renderSize(stats.bytesFreed), stats.filesLinked); + printInfo("%s freed by hard-linking %d files", showBytes(stats.bytesFreed), stats.filesLinked); } void LocalStore::optimisePath(const Path & path, RepairFlag repair) diff --git a/src/libutil-tests/util.cc b/src/libutil-tests/util.cc index 85e4364c2..534731c6c 100644 --- a/src/libutil-tests/util.cc +++ b/src/libutil-tests/util.cc @@ -211,7 +211,6 @@ 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 f7ddf25a8..015086d39 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(int64_t value, bool align = false); +std::string renderSize(uint64_t value, bool align = false); /** * Parse a string into a float. @@ -362,6 +362,8 @@ struct overloaded : Ts... template overloaded(Ts...) -> overloaded; +std::string showBytes(uint64_t bytes); + /** * Provide an addition operator between strings and string_views * inexplicably omitted from the standard library. diff --git a/src/libutil/util.cc b/src/libutil/util.cc index e61963e62..a3d8c9c1e 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -132,16 +132,15 @@ 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(int64_t value, bool align) +std::string renderSize(uint64_t value, bool align) { static const std::array prefixes{{'K', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'}}; size_t power = 0; - double abs_value = std::abs(value); - while (abs_value > 1024 && power < prefixes.size()) { + double res = value; + while (res > 1024 && power < prefixes.size()) { ++power; - abs_value /= 1024; + res /= 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)); } @@ -317,4 +316,9 @@ std::pair getLine(std::string_view s) } } +std::string showBytes(uint64_t bytes) +{ + return fmt("%.2f MiB", bytes / (1024.0 * 1024.0)); +} + } // namespace nix diff --git a/src/nix/diff-closures.cc b/src/nix/diff-closures.cc index baad52cb4..020c3e13b 100644 --- a/src/nix/diff-closures.cc +++ b/src/nix/diff-closures.cc @@ -103,7 +103,8 @@ void printClosureDiff( if (!removed.empty() || !added.empty()) items.push_back(fmt("%s → %s", showVersions(removed), showVersions(added))); if (showDelta) - items.push_back(fmt("%s%s" ANSI_NORMAL, sizeDelta > 0 ? ANSI_RED : ANSI_GREEN, renderSize(sizeDelta))); + items.push_back( + fmt("%s%+.1f KiB" ANSI_NORMAL, sizeDelta > 0 ? ANSI_RED : ANSI_GREEN, sizeDelta / 1024.0)); logger->cout("%s%s: %s", indent, name, concatStringsSep(", ", items)); } } diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc index 146b775e5..fef3ae120 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((int64_t) value, true)); + str << fmt("\t%s", renderSize(value, true)); else str << fmt("\t%11d", value); }