diff options
-rw-r--r-- | doc/manual/command-ref/nix-env.xml | 15 | ||||
-rw-r--r-- | src/libstore/profiles.cc | 23 | ||||
-rw-r--r-- | src/libstore/profiles.hh | 2 | ||||
-rw-r--r-- | src/nix-env/nix-env.cc | 8 |
4 files changed, 42 insertions, 6 deletions
diff --git a/doc/manual/command-ref/nix-env.xml b/doc/manual/command-ref/nix-env.xml index eac7739558be..56c466268ea0 100644 --- a/doc/manual/command-ref/nix-env.xml +++ b/doc/manual/command-ref/nix-env.xml @@ -1346,11 +1346,12 @@ $ nix-env --list-generations <para>This operation deletes the specified generations of the current profile. The generations can be a list of generation numbers, the special value <literal>old</literal> to delete all non-current -generations, or a value such as <literal>30d</literal> to delete all +generations, a value such as <literal>30d</literal> to delete all generations older than the specified number of days (except for the -generation that was active at that point in time). -Periodically deleting old generations is important to make garbage -collection effective.</para> +generation that was active at that point in time), or a value such as. +<literal>+5</literal> to only keep the specified items older than the +current generation. Periodically deleting old generations is important +to make garbage collection effective.</para> </refsection> @@ -1359,6 +1360,8 @@ collection effective.</para> <screen> $ 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</screen> @@ -1458,7 +1461,7 @@ error: no generation older than the current (91) exists</screen> <refsection condition="manpage"><title>Environment variables</title> <variablelist> - + <varlistentry><term><envar>NIX_PROFILE</envar></term> <listitem><para>Location of the Nix profile. Defaults to the @@ -1472,6 +1475,6 @@ error: no generation older than the current (91) exists</screen> </variablelist> </refsection> - + </refentry> diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index 4a607b584506..4c6af567ae6f 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -157,6 +157,29 @@ void deleteGenerations(const Path & profile, const std::set<unsigned int> & 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 (i->number == curGen) { + fromCurGen = true; + max--; + continue; + } + if (fromCurGen) { + if (max) { + max--; + 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 1d4e6d3037db..5fa1533de311 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<unsigned int> & gensToDelete, bool dryRun); +void deleteGenerationsGreaterThan(const Path & profile, const int 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 f60ff9e07182..a43b103f6ec6 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1284,6 +1284,14 @@ 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) { + 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<unsigned int> gens; for (auto & i : opArgs) { |