diff --git a/doc/manual/source/command-ref/nix-collect-garbage.md b/doc/manual/source/command-ref/nix-collect-garbage.md index 8c148b364..c95fe3002 100644 --- a/doc/manual/source/command-ref/nix-collect-garbage.md +++ b/doc/manual/source/command-ref/nix-collect-garbage.md @@ -94,7 +94,7 @@ generations of each profile, do $ nix-collect-garbage -d ``` -## Keep most-recent by time (number fo days) and trim by amount +## Keep most-recent by time (number of days) and trim by amount This command will delete generations older than a week if possible, while keeping an amount of generations between `10` and `20`. diff --git a/src/libstore/include/nix/store/profiles.hh b/src/libstore/include/nix/store/profiles.hh index 1e39de000..577f2bb74 100644 --- a/src/libstore/include/nix/store/profiles.hh +++ b/src/libstore/include/nix/store/profiles.hh @@ -135,17 +135,17 @@ void deleteGenerations(const Path & profile, const std::set & * * Examples: * - All parameters are nullopt - * No generations are deleted - * - keepMax is 5 - * No generations are deleted + * No generations are deleted. + * - keepMin is 5 + * No generations are deleted, only keepMax and olderThan delete generations. * - keepMax is 10 - * 10 generations after the current one are kept, the rest is deleted. + * 10 most recent generations after the current one are kept, the rest is deleted. * - olderThan is 2025-09-16 - * Generations older than 2025-09-16 are deleted + * Generations older than 2025-09-16 are deleted. * - olderThan is 2025-09-16, keepMin is 5, keepMax is 10 - * Will try to delete generations older than 2025-09-16. - * If there are more than 10 generations to be kept, continues to delete old generations until there is 10. - * If there are less than 5 generations to be kept, preserves older generations until there is 5. + * If there are more than 10 generations to be kept, continues to delete old generations until there are 10. + * If there are less than 5 generations to be kept, preserves the most recent of generations to be deleted until there are 5. * * @param profile The profile, specified by its name and location combined into a path, whose generations we want to * delete. diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index ad5810d72..58458f69e 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -166,7 +166,7 @@ static inline void iterDropUntil(Generations & gens, auto && i, auto && cond) void deleteGenerationsFilter(const Path & profile, std::optional olderThan, std::optional keepMin, std::optional keepMax, bool dryRun) { if (keepMin.has_value() && keepMax.has_value() && *keepMin > *keepMax) - throw Error("Keep min cannot be greater than keep max"); + throw Error("--keep-min cannot be greater than --keep-max"); PathLocks lock; lockProfile(lock, profile); @@ -197,13 +197,18 @@ void deleteGenerationsFilter(const Path & profile, std::optional olderTh iterDropUntil(gens, older, [&](auto & g) { return g.creationTime < *olderThan; }); } - // Find first generation to delete by clamping + // Find first generation to delete by clamping between keepMin and keepMax auto toDelete = older; - for (int i = std::distance(gens.rbegin(), older) - std::distance(gens.rbegin(), end); i > 0; --i) + + auto clampBackward = std::distance(gens.rbegin(), older) - std::distance(gens.rbegin(), end); + for (int i = clampBackward; i > 0; --i) --toDelete; - for (int i = std::distance(gens.rbegin(), start) - std::distance(gens.rbegin(), older); i > 0; --i) + + auto clampForward = std::distance(gens.rbegin(), start) - std::distance(gens.rbegin(), older); + for (int i = clampForward; i > 0; --i) ++toDelete; + // Delete for (; toDelete != gens.rend(); ++toDelete) deleteGeneration2(profile, toDelete->number, dryRun); } diff --git a/src/nix/nix-collect-garbage/nix-collect-garbage.cc b/src/nix/nix-collect-garbage/nix-collect-garbage.cc index ce0d8a822..adc25b92a 100644 --- a/src/nix/nix-collect-garbage/nix-collect-garbage.cc +++ b/src/nix/nix-collect-garbage/nix-collect-garbage.cc @@ -83,7 +83,7 @@ static int main_nix_collect_garbage(int argc, char ** argv) deleteOlderThan = std::optional { parseOlderThanTimeSpec(getArg(*arg, arg, end)) }; } else if (*arg == "--keep-min") keepMin = std::optional { std::max(getIntArg(*arg, arg, end, false), (GenerationNumber) 1) }; - else if (*arg == "--keep-max"){ + else if (*arg == "--keep-max") { removeOld = true; keepMax = std::optional { std::max(getIntArg(*arg, arg, end, false), (GenerationNumber) 1) }; }