Implement --delete-generations + flag for keeping last N number of generations

This commit is contained in:
Matthew O'Gorman 2016-01-06 20:15:19 -05:00
parent 4a000cbb39
commit 429154b74c
4 changed files with 32 additions and 2 deletions

View file

@ -1346,9 +1346,10 @@ $ nix-env --list-generations
<para>This operation deletes the specified generations of the current <para>This operation deletes the specified generations of the current
profile. The generations can be a list of generation numbers, the profile. The generations can be a list of generation numbers, the
special value <literal>old</literal> to delete all non-current 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 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.
<literal>+5</literal> to delete all but the number of items specified.
Periodically deleting old generations is important to make garbage Periodically deleting old generations is important to make garbage
collection effective.</para> collection effective.</para>
@ -1359,6 +1360,8 @@ collection effective.</para>
<screen> <screen>
$ nix-env --delete-generations 3 4 8 $ nix-env --delete-generations 3 4 8
$ nix-env --delete-generations +5
$ nix-env --delete-generations 30d $ nix-env --delete-generations 30d
$ nix-env -p other_profile --delete-generations old</screen> $ nix-env -p other_profile --delete-generations old</screen>

View file

@ -157,6 +157,29 @@ void deleteGenerations(const Path & profile, const std::set<unsigned int> & 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) void deleteOldGenerations(const Path & profile, bool dryRun)
{ {

View file

@ -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 deleteGenerations(const Path & profile, const std::set<unsigned int> & gensToDelete, bool dryRun);
void deleteGenerationsGreaterThan(const Path & profile, const string & max, bool dryRun);
void deleteOldGenerations(const Path & profile, bool dryRun); void deleteOldGenerations(const Path & profile, bool dryRun);
void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun); void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun);

View file

@ -1284,6 +1284,8 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr
deleteOldGenerations(globals.profile, globals.dryRun); deleteOldGenerations(globals.profile, globals.dryRun);
} else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) { } else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) {
deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun); 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 { } else {
std::set<unsigned int> gens; std::set<unsigned int> gens;
for (auto & i : opArgs) { for (auto & i : opArgs) {