From 429154b74c7f4b4d679ae79bbc939049f537bfaf Mon Sep 17 00:00:00 2001 From: Matthew O'Gorman Date: Wed, 6 Jan 2016 20:15:19 -0500 Subject: [PATCH 1/5] Implement --delete-generations + flag for keeping last N number of generations --- doc/manual/command-ref/nix-env.xml | 7 +++++-- src/libstore/profiles.cc | 23 +++++++++++++++++++++++ src/libstore/profiles.hh | 2 ++ src/nix-env/nix-env.cc | 2 ++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/doc/manual/command-ref/nix-env.xml b/doc/manual/command-ref/nix-env.xml index d4563ac47..f0e70a41c 100644 --- a/doc/manual/command-ref/nix-env.xml +++ b/doc/manual/command-ref/nix-env.xml @@ -1346,9 +1346,10 @@ $ nix-env --list-generations This operation deletes the specified generations of the current profile. The generations can be a list of generation numbers, the special value old to delete all non-current -generations, or a value such as 30d to delete all +generations, a value such as 30d to delete all generations older than the specified number of days (except for the -generation that was active at that point in time). +generation that was active at that point in time), or a value such as. ++5 to delete all but the number of items specified. Periodically deleting old generations is important to make garbage collection effective. @@ -1359,6 +1360,8 @@ collection effective. $ nix-env --delete-generations 3 4 8 +$ nix-env --delete-generations +5 + $ nix-env --delete-generations 30d $ nix-env -p other_profile --delete-generations old diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index 4a607b584..e6300cf05 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -157,6 +157,29 @@ void deleteGenerations(const Path & profile, const std::set & gens } } +void deleteGenerationsGreaterThan(const Path & profile, const string & max, bool dryRun) +{ + int max_keep = 0; + PathLocks lock; + if(max.size() < 2) + throw Error(format("invalid number of generations ‘%1%’") % max); + string str_max = string(max, 1, max.size()); + if (!string2Int(str_max, max_keep) || max_keep == 0) + throw Error(format("invalid number of generations to keep ‘%1%’") % max); + + lockProfile(lock, profile); + + int curGen; + Generations gens = findGenerations(profile, curGen); + + for (auto i = gens.rbegin(); i != gens.rend(); ++i) { + if (max_keep) { + max_keep--; + continue; + } + deleteGeneration2(profile, i->number, dryRun); + } +} void deleteOldGenerations(const Path & profile, bool dryRun) { diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh index 1d4e6d303..3cad08dc5 100644 --- a/src/libstore/profiles.hh +++ b/src/libstore/profiles.hh @@ -39,6 +39,8 @@ void deleteGeneration(const Path & profile, unsigned int gen); void deleteGenerations(const Path & profile, const std::set & gensToDelete, bool dryRun); +void deleteGenerationsGreaterThan(const Path & profile, const string & max, bool dryRun); + void deleteOldGenerations(const Path & profile, bool dryRun); void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun); diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 97e66cbd9..1440b7744 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1284,6 +1284,8 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr deleteOldGenerations(globals.profile, globals.dryRun); } else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) { deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun); + } else if (opArgs.size() == 1 && opArgs.front().find('+') != string::npos) { + deleteGenerationsGreaterThan(globals.profile, opArgs.front(), globals.dryRun); } else { std::set gens; for (auto & i : opArgs) { From 0312d30315a3a77ab659b742b76ec32685145715 Mon Sep 17 00:00:00 2001 From: Matthew O'Gorman Date: Thu, 19 May 2016 15:42:54 -0400 Subject: [PATCH 2/5] this updates issues that were addressed by people in pr --- src/libstore/profiles.cc | 17 ++++++----------- src/libstore/profiles.hh | 2 +- src/nix-env/nix-env.cc | 8 +++++++- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index e6300cf05..44c3c6e0d 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -157,15 +157,10 @@ void deleteGenerations(const Path & profile, const std::set & gens } } -void deleteGenerationsGreaterThan(const Path & profile, const string & max, bool dryRun) +void deleteGenerationsGreaterThan(const Path & profile, int max, bool dryRun) { int max_keep = 0; PathLocks lock; - if(max.size() < 2) - throw Error(format("invalid number of generations ‘%1%’") % max); - string str_max = string(max, 1, max.size()); - if (!string2Int(str_max, max_keep) || max_keep == 0) - throw Error(format("invalid number of generations to keep ‘%1%’") % max); lockProfile(lock, profile); @@ -173,11 +168,11 @@ void deleteGenerationsGreaterThan(const Path & profile, const string & max, bool Generations gens = findGenerations(profile, curGen); for (auto i = gens.rbegin(); i != gens.rend(); ++i) { - if (max_keep) { - max_keep--; - continue; - } - deleteGeneration2(profile, i->number, dryRun); + if (max) { + max--; + continue; + } + deleteGeneration2(profile, i->number, dryRun); } } diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh index 3cad08dc5..5fa1533de 100644 --- a/src/libstore/profiles.hh +++ b/src/libstore/profiles.hh @@ -39,7 +39,7 @@ void deleteGeneration(const Path & profile, unsigned int gen); void deleteGenerations(const Path & profile, const std::set & gensToDelete, bool dryRun); -void deleteGenerationsGreaterThan(const Path & profile, const string & max, bool dryRun); +void deleteGenerationsGreaterThan(const Path & profile, const int max, bool dryRun); void deleteOldGenerations(const Path & profile, bool dryRun); diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 1440b7744..0da31588d 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1285,7 +1285,13 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr } else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) { deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun); } else if (opArgs.size() == 1 && opArgs.front().find('+') != string::npos) { - deleteGenerationsGreaterThan(globals.profile, opArgs.front(), globals.dryRun); + if(opArgs.front().size() < 2) + throw Error(format("invalid number of generations ‘%1%’") % opArgs.front()); + string str_max = string(opArgs.front() 1, opArgs.front().size()); + int max; + if (!string2Int(str_max, max) || max == 0) + throw Error(format("invalid number of generations to keep ‘%1%’") % opArgs.front()); + deleteGenerationsGreaterThan(globals.profile, max, globals.dryRun); } else { std::set gens; for (auto & i : opArgs) { From 12fe2249e1b32dc9033e2680017a4c7f236edaac Mon Sep 17 00:00:00 2001 From: Matt O'Gorman Date: Thu, 21 Sep 2017 21:41:19 -0400 Subject: [PATCH 3/5] Update nix-env.cc missing comma --- src/nix-env/nix-env.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 0da31588d..f6a9d9e7b 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1287,7 +1287,7 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr } else if (opArgs.size() == 1 && opArgs.front().find('+') != string::npos) { if(opArgs.front().size() < 2) throw Error(format("invalid number of generations ‘%1%’") % opArgs.front()); - string str_max = string(opArgs.front() 1, opArgs.front().size()); + string str_max = string(opArgs.front(), 1, opArgs.front().size()); int max; if (!string2Int(str_max, max) || max == 0) throw Error(format("invalid number of generations to keep ‘%1%’") % opArgs.front()); From 3c16044cb0acc87e128534cb3e2a2006b71059b6 Mon Sep 17 00:00:00 2001 From: Matthew O'Gorman Date: Thu, 1 Mar 2018 22:22:02 -0500 Subject: [PATCH 4/5] remove unused variable and make sure to check that the current generation is not the one we are deleting --- src/libstore/profiles.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index 44c3c6e0d..b43ec66f6 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -159,7 +159,6 @@ void deleteGenerations(const Path & profile, const std::set & gens void deleteGenerationsGreaterThan(const Path & profile, int max, bool dryRun) { - int max_keep = 0; PathLocks lock; lockProfile(lock, profile); @@ -172,7 +171,8 @@ void deleteGenerationsGreaterThan(const Path & profile, int max, bool dryRun) max--; continue; } - deleteGeneration2(profile, i->number, dryRun); + if (i->number != curGen) + deleteGeneration2(profile, i->number, dryRun); } } From 467fdd8ca4d63972dbd94f0496918522c58916a0 Mon Sep 17 00:00:00 2001 From: Matthew O'Gorman Date: Thu, 1 Mar 2018 22:59:00 -0500 Subject: [PATCH 5/5] only delete things older than current gen and update logic in doc as well --- doc/manual/command-ref/nix-env.xml | 10 +++++----- src/libstore/profiles.cc | 13 +++++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/doc/manual/command-ref/nix-env.xml b/doc/manual/command-ref/nix-env.xml index f0e70a41c..7eb9cc855 100644 --- a/doc/manual/command-ref/nix-env.xml +++ b/doc/manual/command-ref/nix-env.xml @@ -1349,9 +1349,9 @@ special value old to delete all non-current generations, a value such as 30d to delete all generations older than the specified number of days (except for the generation that was active at that point in time), or a value such as. -+5 to delete all but the number of items specified. -Periodically deleting old generations is important to make garbage -collection effective. ++5 to only keep the specified items older than the +current generation. Periodically deleting old generations is important +to make garbage collection effective. @@ -1461,7 +1461,7 @@ error: no generation older than the current (91) exists Environment variables - + NIX_PROFILE Location of the Nix profile. Defaults to the @@ -1475,6 +1475,6 @@ error: no generation older than the current (91) exists - + diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index b43ec66f6..4c6af567a 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -160,19 +160,24 @@ void deleteGenerations(const Path & profile, const std::set & gens void deleteGenerationsGreaterThan(const Path & profile, int max, bool dryRun) { PathLocks lock; - lockProfile(lock, profile); int curGen; + bool fromCurGen = false; Generations gens = findGenerations(profile, curGen); - for (auto i = gens.rbegin(); i != gens.rend(); ++i) { - if (max) { + if (i->number == curGen) { + fromCurGen = true; max--; continue; } - if (i->number != curGen) + if (fromCurGen) { + if (max) { + max--; + continue; + } deleteGeneration2(profile, i->number, dryRun); + } } }