nixos-rebuild: Add list-generations

Add new command `nixos-rebuild list-generations`. It will show an output
like

```
$ nixos-rebuild list-generations
Generation      Build-date               NixOS version           Kernel  Configuration Revision                    Specialisations
52   (current)  Fri 2023-08-18 08:17:27  23.11.20230817.0f46300  6.4.10  448160aeccf6a7184bd8a84290d527819f1c552c  *
51              Mon 2023-08-07 17:56:41  23.11.20230807.31b1eed  6.4.8   99ef480007ca51e3d440aa4fa6558178d63f9c42  *
```

This also mentions the change in the upcoming release notes
This commit is contained in:
Michael Lohmann 2023-02-12 17:31:09 +01:00
parent a1635b3821
commit cc625486c4
4 changed files with 100 additions and 3 deletions

View file

@ -8,6 +8,8 @@
- LXD now supports virtual machine instances to complement the existing container support
- The `nixos-rebuild` command has been given a `list-generations` subcommand. See `man nixos-rebuild` for more details.
## New Services {#sec-release-23.11-new-services}
- [MCHPRS](https://github.com/MCHPR/MCHPRS), a multithreaded Minecraft server built for redstone. Available as [services.mchprs](#opt-services.mchprs.enable).

View file

@ -3,6 +3,8 @@
, coreutils
, gnused
, gnugrep
, jq
, util-linux
, nix
, lib
, nixosTests
@ -20,7 +22,7 @@ substituteAll {
nix_x86_64_linux = fallback.x86_64-linux;
nix_i686_linux = fallback.i686-linux;
nix_aarch64_linux = fallback.aarch64-linux;
path = lib.makeBinPath [ coreutils gnused gnugrep ];
path = lib.makeBinPath [ coreutils gnused gnugrep jq util-linux ];
nativeBuildInputs = [
installShellFiles
];

View file

@ -10,7 +10,7 @@
.Sh SYNOPSIS
.Nm
.Bro
.Cm switch | boot | test | build | dry-build | dry-activate | edit | build-vm | build-vm-with-bootloader
.Cm switch | boot | test | build | dry-build | dry-activate | edit | build-vm | build-vm-with-bootloader | list-generations Op Fl -json
.Brc
.br
.Op Fl -upgrade | -upgrade-all
@ -196,6 +196,14 @@ The boot loader is installed on an automatically generated virtual disk
containing a
.Pa /boot
partition.
.
.It Cm list-generations Op Fl -json
List the available generations in a similar manner to the boot loader
menu. It shows the generation number, build date and time, NixOS version,
kernel version and the configuration revision. This is useful to get
information e.g. for which generation to roll back to with
.Ic nixos-rebuild switch Fl -generation Ar N
There is also a json version of output available.
.El
.
.

View file

@ -36,6 +36,7 @@ verboseScript=
noFlake=
# comma separated list of vars to preserve when using sudo
preservedSudoVars=NIXOS_INSTALL_BOOTLOADER
json=
# log the given argument to stderr
log() {
@ -48,7 +49,7 @@ while [ "$#" -gt 0 ]; do
--help)
showSyntax
;;
switch|boot|test|build|edit|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader)
switch|boot|test|build|edit|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader|list-generations)
if [ "$i" = dry-run ]; then i=dry-build; fi
# exactly one action mandatory, bail out if multiple are given
if [ -n "$action" ]; then showSyntax; fi
@ -146,6 +147,9 @@ while [ "$#" -gt 0 ]; do
k="$1"; shift 1
lockFlags+=("$i" "$j" "$k")
;;
--json)
json=1
;;
*)
log "$0: unknown option \`$i'"
exit 1
@ -507,6 +511,87 @@ if [ "$action" = dry-build ]; then
extraBuildFlags+=(--dry-run)
fi
if [ "$action" = list-generations ]; then
if [ ! -L "$profile" ]; then
log "No profile \`$(basename "$profile")' found"
exit 1
fi
generation_from_dir() {
generation_dir="$1"
generation_base="$(basename "$generation_dir")" # Has the format "system-123-link" for generation 123
no_link_gen="${generation_base%-link}" # remove the "-link"
echo "${no_link_gen##*-}" # remove everything before the last dash
}
describe_generation(){
generation_dir="$1"
generation_number="$(generation_from_dir "$generation_dir")"
nixos_version="$(cat "$generation_dir/nixos-version" 2> /dev/null || echo "Unknown")"
kernel_dir="$(dirname "$(realpath "$generation_dir/kernel")")"
kernel_version="$(ls "$kernel_dir/lib/modules" || echo "Unknown")"
configurationRevision="$("$generation_dir/sw/bin/nixos-version" --configuration-revision 2> /dev/null || true)"
# Old nixos-version output ignored unknown flags and just printed the version
# therefore the following workaround is done not to show the default output
nixos_version_default="$("$generation_dir/sw/bin/nixos-version")"
if [ "$configurationRevision" == "$nixos_version_default" ]; then
configurationRevision=""
fi
# jq automatically quotes the output => don't try to quote it in output!
build_date="$(stat "$generation_dir" --format=%W | jq 'todate')"
pushd "$generation_dir/specialisation/" > /dev/null || :
specialisation_list=(*)
popd > /dev/null || :
specialisations="$(jq --compact-output --null-input '$ARGS.positional' --args -- "${specialisation_list[@]}")"
if [ "$(basename "$generation_dir")" = "$(readlink "$profile")" ]; then
current_generation_tag="true"
else
current_generation_tag="false"
fi
# Escape userdefined strings
nixos_version="$(jq -aR <<< "$nixos_version")"
kernel_version="$(jq -aR <<< "$kernel_version")"
configurationRevision="$(jq -aR <<< "$configurationRevision")"
cat << EOF
{
"generation": $generation_number,
"date": $build_date,
"nixosVersion": $nixos_version,
"kernelVersion": $kernel_version,
"configurationRevision": $configurationRevision,
"specialisations": $specialisations,
"current": $current_generation_tag
}
EOF
}
find "$(dirname "$profile")" -regex "$profile-[0-9]+-link" |
sort -Vr |
while read -r generation_dir; do
describe_generation "$generation_dir"
done |
if [ -z "$json" ]; then
jq --slurp -r '.[] | [
([.generation, (if .current == true then "current" else "" end)] | join(" ")),
(.date | fromdate | strflocaltime("%Y-%m-%d %H:%M:%S")),
.nixosVersion, .kernelVersion, .configurationRevision,
(.specialisations | join(" "))
] | @tsv' |
column --separator $'\t' --table --table-columns "Generation,Build-date,NixOS version,Kernel,Configuration Revision,Specialisation" |
${PAGER:cat}
else
jq --slurp .
fi
exit 0
fi
# Either upgrade the configuration in the system profile (for "switch"
# or "boot"), or just build it and create a symlink "result" in the