diff --git a/doc/manual/nix-store.xml b/doc/manual/nix-store.xml
index 63ddef28e..416438a0b 100644
--- a/doc/manual/nix-store.xml
+++ b/doc/manual/nix-store.xml
@@ -296,8 +296,12 @@ options control what gets deleted and in what order:
bytesKeep deleting paths until at least
- bytes bytes have been
- deleted, then stop.
+ bytes bytes have been deleted, then
+ stop. The argument bytes can be
+ followed by the multiplicative suffix K,
+ M, G or
+ T, denoting KiB, MiB, GiB or TiB
+ units.
diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh
index ff89e8638..b29b08bb5 100644
--- a/src/libmain/shared.hh
+++ b/src/libmain/shared.hh
@@ -4,6 +4,8 @@
#include
+#include
+
/* These are not implemented here, but must be implemented by a
program linking against libmain. */
@@ -35,14 +37,27 @@ void printMissing(const PathSet & willBuild,
unsigned long long downloadSize, unsigned long long narSize);
template N getIntArg(const string & opt,
- Strings::iterator & i, const Strings::iterator & end)
+ Strings::iterator & i, const Strings::iterator & end, bool allowUnit)
{
++i;
if (i == end) throw UsageError(format("`%1%' requires an argument") % opt);
+ string s = *i;
+ N multiplier = 1;
+ if (allowUnit && !s.empty()) {
+ char u = std::toupper(*s.rbegin());
+ if (std::isalpha(u)) {
+ if (u == 'K') multiplier = 1ULL << 10;
+ else if (u == 'M') multiplier = 1ULL << 20;
+ else if (u == 'G') multiplier = 1ULL << 30;
+ else if (u == 'T') multiplier = 1ULL << 40;
+ else throw UsageError(format("invalid unit specifier `%1%'") % u);
+ s.resize(s.size() - 1);
+ }
+ }
N n;
- if (!string2Int(*i, n))
+ if (!string2Int(s, n))
throw UsageError(format("`%1%' requires an integer argument") % opt);
- return n;
+ return n * multiplier;
}
/* Show the manual page for the specified program. */
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 365ffa19a..e969a3b71 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -619,7 +619,7 @@ static void opGC(Strings opFlags, Strings opArgs)
else if (*i == "--print-dead") options.action = GCOptions::gcReturnDead;
else if (*i == "--delete") options.action = GCOptions::gcDeleteDead;
else if (*i == "--max-freed") {
- long long maxFreed = getIntArg(*i, i, opFlags.end());
+ long long maxFreed = getIntArg(*i, i, opFlags.end(), true);
options.maxFreed = maxFreed >= 0 ? maxFreed : 0;
}
else throw UsageError(format("bad sub-operation `%1%' in GC") % *i);