nix-env: Minor change to '--delete-generations Nd' semantics

The option '--delete-generations Nd' deletes all generations older than N
days. However, most likely the user does not want to delete the
generation that was active N days ago.

For example, say that you have these 3 generations:

1: <30 days ago>
2: <15 days ago>
3: <1 hour ago>

If you do --delete-generations 7d (say, as part of a cron job), most
likely you still want to keep generation 2, i.e. the generation that was
active 7 days ago (and for most of the past 7 days, in fact).

This patch fixes this issue. Note that this also affects
'nix-collect-garbage --delete-older-than Nd'.

Thanks to @roconnor for noticing the issue!
This commit is contained in:
Ricardo M. Correia 2014-04-11 17:10:20 +02:00 committed by Eelco Dolstra
parent fb5d76b89e
commit 700c678c2e
3 changed files with 15 additions and 7 deletions

View file

@ -45,8 +45,9 @@ which deletes all old generations of all profiles in
impossible); and
<option>--delete-older-than</option> <replaceable>period</replaceable>,
where period is a value such as <literal>30d</literal>, which deletes
all non-current generations that are older than the specified number of
days in all profiles in <filename>/nix/var/nix/profiles</filename>.
all generations older than the specified number of days in all profiles
in <filename>/nix/var/nix/profiles</filename> (except for the generations
that were active at that point in time).
</para>
</refsection>

View file

@ -1170,7 +1170,8 @@ $ nix-env --list-generations
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
non-current generations older than the specified number of days.
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>

View file

@ -1315,11 +1315,17 @@ static void opDeleteGenerations(Globals & globals,
oldTime = curTime - days * 24 * 3600;
for (Generations::iterator j = gens.begin(); j != gens.end(); ++j) {
if (j->number == curGen) continue;
if (j->creationTime < oldTime)
bool canDelete = false;
for (Generations::reverse_iterator j = gens.rbegin(); j != gens.rend(); ++j) {
if (canDelete) {
assert(j->creationTime < oldTime);
deleteGeneration2(globals, j->number);
} else if (j->creationTime < oldTime) {
/* We may now start deleting generations, but we don't delete
this generation yet, because this generation was still the
one that was active at the requested point in time. */
canDelete = true;
}
}
} else {
int n;