diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index 4de4e126d..6bec2e515 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -139,8 +139,7 @@ void deleteGeneration(const Path & profile, GenerationNumber gen, bool dryRun) } } - -void deleteGenerations(const Path & profile, const std::set & gensToDelete, bool dryRun) +void deleteNumberedGenerations(const Path & profile, const std::set & gensToDelete, bool dryRun) { PathLocks lock; lockProfile(lock, profile); @@ -249,6 +248,26 @@ time_t parseOlderThanTimeSpec(std::string_view timeSpec) return curTime - *days * 24 * 3600; } +void deleteUnusedGenerations(const Path & profile, std::string_view period, bool dryRun) { + if (period == "old") { + deleteOldGenerations(profile, dryRun); + } else if (period.find('d') != std::string::npos) { + auto t = parseOlderThanTimeSpec(period); + deleteGenerationsOlderThan(profile, t, dryRun); + } else if (period.find('+') != std::string::npos) { + if (period.size() < 2) + throw Error("invalid number of generations '%1%'", period); + auto str_max = period.substr(1); + auto max = string2Int(str_max); + if (!max) + throw Error("invalid number of generations to keep '%1%'", period); + deleteGenerationsGreaterThan(profile, *max, dryRun); + } else { + throw Error("invalid generation to delete '%1%'", period); + } +} + + void switchLink(Path link, Path target) { diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh index 7e7bbf04d..b322f9402 100644 --- a/src/libstore/profiles.hh +++ b/src/libstore/profiles.hh @@ -128,48 +128,23 @@ void deleteGeneration(const Path & profile, GenerationNumber gen, bool dryRun); * Trying to delete the currently active generation will fail, and cause * no generations to be deleted. */ -void deleteGenerations(const Path & profile, const std::set & gensToDelete, bool dryRun); +void deleteNumberedGenerations(const Path & profile, const std::set & gensToDelete, bool dryRun); /** - * Delete generations older than `max` passed the current generation. + * Delete unused generations. * * @param profile The profile, specified by its name and location combined into a path, whose generations we want to delete. * - * @param max How many generations to keep up to the current one. Must - * be at least 1 so we don't delete the current one. + * @param period Specifies which generations to keep. + * "old" removes all unused generations. + * "+*N*" will keep up to *N* generations older than the current generation. + * "*N*d" will keep up to *N* days older than the current generation * * @param dryRun Log what would be deleted instead of actually doing * so. */ -void deleteGenerationsGreaterThan(const Path & profile, GenerationNumber max, bool dryRun); +void deleteUnusedGenerations(const Path & profile, std::string_view period, bool dryRun); -/** - * Delete all generations other than the current one - * - * @param profile The profile, specified by its name and location combined into a path, whose generations we want to delete. - * - * @param dryRun Log what would be deleted instead of actually doing - * so. - */ -void deleteOldGenerations(const Path & profile, bool dryRun); - -/** - * Delete generations older than `t`, except for the most recent one - * older than `t`. - * - * @param profile The profile, specified by its name and location combined into a path, whose generations we want to delete. - * - * @param dryRun Log what would be deleted instead of actually doing - * so. - */ -void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun); - -/** - * Parse a temp spec intended for `deleteGenerationsOlderThan()`. - * - * Throws an exception if `timeSpec` fails to parse. - */ -time_t parseOlderThanTimeSpec(std::string_view timeSpec); /** * Smaller wrapper around `replaceSymlink` for replacing the current diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc index 91209c978..ce35b4aae 100644 --- a/src/nix-collect-garbage/nix-collect-garbage.cc +++ b/src/nix-collect-garbage/nix-collect-garbage.cc @@ -13,7 +13,7 @@ using namespace nix; -std::string deleteOlderThan; +std::string deletePeriod = "old"; bool dryRun = false; @@ -43,11 +43,7 @@ void removeOldGenerations(std::string dir) } if (link.find("link") != std::string::npos) { printInfo("removing old generations of profile %s", path); - if (deleteOlderThan != "") { - auto t = parseOlderThanTimeSpec(deleteOlderThan); - deleteGenerationsOlderThan(path, t, dryRun); - } else - deleteOldGenerations(path, dryRun); + deleteUnusedGenerations(path, deletePeriod, dryRun); } } else if (type == std::filesystem::file_type::directory) { removeOldGenerations(path); @@ -70,7 +66,7 @@ static int main_nix_collect_garbage(int argc, char * * argv) else if (*arg == "--delete-old" || *arg == "-d") removeOld = true; else if (*arg == "--delete-older-than") { removeOld = true; - deleteOlderThan = getArg(*arg, arg, end); + deletePeriod = getArg(*arg, arg, end); } else if (*arg == "--dry-run") dryRun = true; else if (*arg == "--max-freed") diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index c72378cd5..9fdf27d44 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1366,19 +1366,8 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr if (opFlags.size() > 0) throw UsageError("unknown flag '%1%'", opFlags.front()); - if (opArgs.size() == 1 && opArgs.front() == "old") { - deleteOldGenerations(globals.profile, globals.dryRun); - } else if (opArgs.size() == 1 && opArgs.front().find('d') != std::string::npos) { - auto t = parseOlderThanTimeSpec(opArgs.front()); - deleteGenerationsOlderThan(globals.profile, t, globals.dryRun); - } else if (opArgs.size() == 1 && opArgs.front().find('+') != std::string::npos) { - if (opArgs.front().size() < 2) - throw Error("invalid number of generations '%1%'", opArgs.front()); - auto str_max = opArgs.front().substr(1); - auto max = string2Int(str_max); - if (!max) - throw Error("invalid number of generations to keep '%1%'", opArgs.front()); - deleteGenerationsGreaterThan(globals.profile, *max, globals.dryRun); + if (opArgs.size() == 1) { + deleteUnusedGenerations(globals.profile, opArgs.front(), globals.dryRun); } else { std::set gens; for (auto & i : opArgs) { @@ -1387,7 +1376,7 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr else throw UsageError("invalid generation number '%1%'", i); } - deleteGenerations(globals.profile, gens, globals.dryRun); + deleteNumberedGenerations(globals.profile, gens, globals.dryRun); } } diff --git a/src/nix/profile.cc b/src/nix/profile.cc index c89b8c9bd..eca07b854 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -960,11 +960,8 @@ struct CmdProfileWipeHistory : virtual StoreCommand, MixDefaultProfile, MixDryRu void run(ref store) override { - if (minAge) { - auto t = parseOlderThanTimeSpec(*minAge); - deleteGenerationsOlderThan(*profile, t, dryRun); - } else - deleteOldGenerations(*profile, dryRun); + auto period = minAge ? *minAge : "old"; + deleteUnusedGenerations(*profile, period, dryRun); } };