Merge pull request #8351 from obsidiansystems/delete-profiles-tests-docs

Expanding tests and docs relating to deleting profiles
This commit is contained in:
John Ericson 2023-06-15 01:47:21 +02:00 committed by GitHub
commit 946cd9e3f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 146 additions and 49 deletions

View file

@ -1,6 +1,6 @@
# Name # Name
`nix-collect-garbage` - delete unreachable store paths `nix-collect-garbage` - delete unreachable [store objects]
# Synopsis # Synopsis
@ -8,17 +8,57 @@
# Description # Description
The command `nix-collect-garbage` is mostly an alias of [`nix-store The command `nix-collect-garbage` is mostly an alias of [`nix-store --gc`](@docroot@/command-ref/nix-store/gc.md).
--gc`](@docroot@/command-ref/nix-store/gc.md), that is, it deletes all That is, it deletes all unreachable [store objects] in the Nix store to clean up your system.
unreachable paths in the Nix store to clean up your system. However,
it provides two additional options: `-d` (`--delete-old`), which However, it provides two additional options,
deletes all old generations of all profiles in `/nix/var/nix/profiles` [`--delete-old`](#opt-delete-old) and [`--delete-older-than`](#opt-delete-older-than),
by invoking `nix-env --delete-generations old` on all profiles (of which also delete old [profiles], allowing potentially more [store objects] to be deleted because profiles are also garbage collection roots.
course, this makes rollbacks to previous configurations impossible); These options are the equivalent of running
and `--delete-older-than` *period*, where period is a value such as [`nix-env --delete-generations`](@docroot@/command-ref/nix-env/delete-generations.md)
`30d`, which deletes all generations older than the specified number with various augments on multiple profiles,
of days in all profiles in `/nix/var/nix/profiles` (except for the prior to running `nix-collect-garbage` (or just `nix-store --gc`) without any flags.
generations that were active at that point in time).
> **Note**
>
> Deleting previous configurations makes rollbacks to them impossible.
These flags should be used with care, because they potentially delete generations of profiles used by other users on the system.
## Locations searched for profiles
`nix-collect-garbage` cannot know about all profiles; that information doesn't exist.
Instead, it looks in a few locations, and acts on all profiles it finds there:
1. The default profile locations as specified in the [profiles] section of the manual.
2. > **NOTE**
>
> Not stable; subject to change
>
> Do not rely on this functionality; it just exists for migration purposes and is may change in the future.
> These deprecated paths remain a private implementation detail of Nix.
`$NIX_STATE_DIR/profiles` and `$NIX_STATE_DIR/profiles/per-user`.
With the exception of `$NIX_STATE_DIR/profiles/per-user/root` and `$NIX_STATE_DIR/profiles/default`, these directories are no longer used by other commands.
`nix-collect-garbage` looks there anyways in order to clean up profiles from older versions of Nix.
# Options
These options are for deleting old [profiles] prior to deleting unreachable [store objects].
- <span id="opt-delete-old">[`--delete-old`](#opt-delete-old)</span> / `-d`\
Delete all old generations of profiles.
This is the equivalent of invoking `nix-env --delete-generations old` on each found profile.
- <span id="opt-delete-older-than">[`--delete-older-than`](#opt-delete-older-than)</span> *period*\
Delete all generations of profiles older than the specified amount (except for the generations that were active at that point in time).
*period* is a value such as `30d`, which would mean 30 days.
This is the equivalent of invoking [`nix-env --delete-generations <period>`](@docroot@/command-ref/nix-env/delete-generations.md#generations-days) on each found profile.
See the documentation of that command for additional information about the *period* argument.
{{#include ./opt-common.md}} {{#include ./opt-common.md}}
@ -32,3 +72,6 @@ generations of each profile, do
```console ```console
$ nix-collect-garbage -d $ nix-collect-garbage -d
``` ```
[profiles]: @docroot@/command-ref/files/profiles.md
[store objects]: @docroot@/glossary.md#gloss-store-object

View file

@ -9,14 +9,39 @@
# Description # Description
This operation deletes the specified generations of the current profile. 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, a value such as `30d` to *generations* can be a one of the following:
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 - <span id="generations-list">`<number>...`</span>:\
such as `+5` to keep the last `5` generations ignoring any newer than A list of generation numbers, each one a separate command-line argument.
current, e.g., if `30` is the current generation `+5` will delete
generation `25` and all older generations. Periodically deleting old Delete exactly the profile generations given by their generation number.
generations is important to make garbage collection effective. Deleting the current generation is not allowed.
- The special value <span id="generations-old">`old`</span>
Delete all generations older than the current one.
- <span id="generations-days">`<days>d`</span>:\
The last *days* days
*Example*: `30d`
Delete all generations older than *days* days.
The generation that was active at that point in time is excluded, and will not be deleted.
- <span id="generations-count">`+<count>`</span>:\
The last *count* generations up to the present
*Example*: `+5`
Keep the last *count* generations, along with any newer than current.
Periodically deleting old generations is important to make garbage collection
effective.
The is because profiles are also garbage collection roots — any [store object] reachable from a profile is "alive" and ineligible for deletion.
[store object]: @docroot@/glossary.md#gloss-store-object
{{#include ./opt-common.md}} {{#include ./opt-common.md}}
@ -28,19 +53,35 @@ generations is important to make garbage collection effective.
# Examples # Examples
## Delete explicit generation numbers
```console ```console
$ nix-env --delete-generations 3 4 8 $ nix-env --delete-generations 3 4 8
``` ```
Delete the generations numbered 3, 4, and 8, so long as the current active generation is not any of those.
## Keep most-recent by count count
```console ```console
$ nix-env --delete-generations +5 $ nix-env --delete-generations +5
``` ```
Suppose `30` is the current generation, and we currently have generations numbered `20` through `32`.
Then this command will delete generations `20` through `25` (`<= 30 - 5`),
and keep generations `26` through `31` (`> 30 - 5`).
## Keep most-recent in days
```console ```console
$ nix-env --delete-generations 30d $ nix-env --delete-generations 30d
``` ```
This command will delete all generations older than 30 days, except for the generation that was active 30 days ago (if it currently exists).
## Delete all older
```console ```console
$ nix-env --profile other_profile --delete-generations old $ nix-env --profile other_profile --delete-generations old
``` ```

View file

@ -50,31 +50,3 @@ if test -e $outPath/foobar; then false; fi
# Check that the store is empty. # Check that the store is empty.
rmdir $NIX_STORE_DIR/.links rmdir $NIX_STORE_DIR/.links
rmdir $NIX_STORE_DIR rmdir $NIX_STORE_DIR
## Test `nix-collect-garbage -d`
testCollectGarbageD () {
clearProfiles
# Run two `nix-env` commands, should create two generations of
# the profile
nix-env -f ./user-envs.nix -i foo-1.0
nix-env -f ./user-envs.nix -i foo-2.0pre1
[[ $(nix-env --list-generations | wc -l) -eq 2 ]]
# Clear the profile history. There should be only one generation
# left
nix-collect-garbage -d
[[ $(nix-env --list-generations | wc -l) -eq 1 ]]
}
# `nix-env` doesn't work with CA derivations, so let's ignore that bit if we're
# using them
if [[ -z "${NIX_TESTS_CA_BY_DEFAULT:-}" ]]; then
testCollectGarbageD
# Run the same test, but forcing the profiles at their legacy location under
# /nix/var/nix.
#
# Regression test for #8294
rm ~/.nix-profile
ln -s $NIX_STATE_DIR/profiles/per-user/me ~/.nix-profile
testCollectGarbageD
fi

View file

@ -16,6 +16,7 @@ nix_tests = \
flakes/flake-in-submodule.sh \ flakes/flake-in-submodule.sh \
ca/gc.sh \ ca/gc.sh \
gc.sh \ gc.sh \
nix-collect-garbage-d.sh \
remote-store.sh \ remote-store.sh \
legacy-ssh-store.sh \ legacy-ssh-store.sh \
lang.sh \ lang.sh \

View file

@ -0,0 +1,40 @@
source common.sh
clearStore
## Test `nix-collect-garbage -d`
# TODO make `nix-env` doesn't work with CA derivations, and make
# `ca/nix-collect-garbage-d.sh` wrapper.
testCollectGarbageD () {
clearProfiles
# Run two `nix-env` commands, should create two generations of
# the profile
nix-env -f ./user-envs.nix -i foo-1.0 "$@"
nix-env -f ./user-envs.nix -i foo-2.0pre1 "$@"
[[ $(nix-env --list-generations "$@" | wc -l) -eq 2 ]]
# Clear the profile history. There should be only one generation
# left
nix-collect-garbage -d
[[ $(nix-env --list-generations "$@" | wc -l) -eq 1 ]]
}
testCollectGarbageD
# Run the same test, but forcing the profiles an arbitrary location.
rm ~/.nix-profile
ln -s $TEST_ROOT/blah ~/.nix-profile
testCollectGarbageD
# Run the same test, but forcing the profiles at their legacy location under
# /nix/var/nix.
#
# Note that we *don't* use the default profile; `nix-collect-garbage` will
# need to check the legacy conditional unconditionally not just follow
# `~/.nix-profile` to pass this test.
#
# Regression test for #8294
rm ~/.nix-profile
testCollectGarbageD --profile "$NIX_STATE_DIR/profiles/per-user/me"