From e5bcb378fae0e38379b0b365ab2a2431ae5d6c07 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2013 19:13:26 +0200 Subject: [PATCH] Add support for multiple system profiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ‘nixos-rebuild’ now accepts an argument ‘--profile-name’ (or ‘-p’), denoting the name of a system profile to use. The default is ‘system’, which maps to /nix/var/nix/profiles/system. Any other value maps to /nix/var/nix/profiles/system-profiles/. The GRUB menu generator makes all system profiles available as submenus. For instance, doing $ nixos-rebuild boot -p test will cause a menu named ‘NixOS - Profile 'test'’ to be added to the GRUB boot menu, leaving the default system profile unaffected. This is only supported for GRUB 2. --- modules/installer/tools/nixos-rebuild.sh | 30 +++++++---- .../system/boot/loader/grub/install-grub.pl | 53 ++++++++++++------- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/modules/installer/tools/nixos-rebuild.sh b/modules/installer/tools/nixos-rebuild.sh index 8597cf165b15d2..8734cb273d4908 100644 --- a/modules/installer/tools/nixos-rebuild.sh +++ b/modules/installer/tools/nixos-rebuild.sh @@ -24,10 +24,10 @@ Options: --upgrade fetch the latest version of NixOS before rebuilding --install-grub (re-)install the Grub bootloader --no-build-nix don't build the latest Nix from Nixpkgs before - building NixOS + building NixOS --rollback restore the previous NixOS configuration (only - with switch, boot, test, build) - + with switch, boot, test, build) + --profile-name / -p install in the specified system profile --fast same as --no-build-nix --show-trace Various nix-build options are also accepted, in particular: @@ -50,6 +50,7 @@ buildNix=1 rollback= upgrade= repair= +profile=/nix/var/nix/profiles/system while [ "$#" -gt 0 ]; do i="$1"; shift 1 @@ -92,6 +93,17 @@ while [ "$#" -gt 0 ]; do buildNix= extraBuildFlags+=(--show-trace) ;; + --profile-name|-p) + if [ -z "$1" ]; then + echo "$0: ‘--profile-name’ requires an argument" + exit 1 + fi + if [ "$1" != system ]; then + profile="/nix/var/nix/profiles/system-profiles/$1" + mkdir -p -m 0755 "$(dirname "$profile")" + fi + shift 1 + ;; *) echo "$0: unknown option \`$i'" exit 1 @@ -164,8 +176,8 @@ fi if [ -z "$rollback" ]; then echo "building the system configuration..." >&2 if [ "$action" = switch -o "$action" = boot ]; then - nix-env "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/system -f '' --set -A system - pathToConfig=/nix/var/nix/profiles/system + nix-env "${extraBuildFlags[@]}" -p "$profile" -f '' --set -A system + pathToConfig="$profile" elif [ "$action" = test -o "$action" = build -o "$action" = dry-run ]; then nix-build '' -A system -K -k "${extraBuildFlags[@]}" > /dev/null pathToConfig=./result @@ -180,14 +192,14 @@ if [ -z "$rollback" ]; then fi else # [ -n "$rollback" ] if [ "$action" = switch -o "$action" = boot ]; then - nix-env --rollback -p /nix/var/nix/profiles/system - pathToConfig=/nix/var/nix/profiles/system + nix-env --rollback -p "$profile" + pathToConfig="$profile" elif [ "$action" = test -o "$action" = build ]; then systemNumber=$( - nix-env -p /nix/var/nix/profiles/system --list-generations | + nix-env -p "$profile" --list-generations | sed -n '/current/ {g; p;}; s/ *\([0-9]*\).*/\1/; h' ) - ln -sT /nix/var/nix/profiles/system-${systemNumber}-link ./result + ln -sT "$profile"-${systemNumber}-link ./result pathToConfig=./result else showSyntax diff --git a/modules/system/boot/loader/grub/install-grub.pl b/modules/system/boot/loader/grub/install-grub.pl index 738714ba714848..a83733db63b0cc 100644 --- a/modules/system/boot/loader/grub/install-grub.pl +++ b/modules/system/boot/loader/grub/install-grub.pl @@ -193,27 +193,42 @@ sub addEntry { # extraEntries could refer to @bootRoot@, which we have to substitute $conf =~ s/\@bootRoot\@/$bootRoot/g; -# Add entries for all previous generations of the system profile. -$conf .= "submenu \"NixOS - All configurations\" {\n" if $grubVersion == 2; - -sub nrFromGen { my ($x) = @_; $x =~ /system-(.*)-link/; return $1; } - -my @links = sort - { nrFromGen($b) <=> nrFromGen($a) } - (glob "/nix/var/nix/profiles/system-*-link"); - -my $curEntry = 0; -foreach my $link (@links) { - last if $curEntry++ >= $configurationLimit; - my $date = strftime("%F", localtime(lstat($link)->mtime)); - my $version = - -e "$link/nixos-version" - ? readFile("$link/nixos-version") - : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); - addEntry("NixOS - Configuration " . nrFromGen($link) . " ($date - $version)", $link); +# Emit submenus for all system profiles. +sub addProfile { + my ($profile, $description) = @_; + + # Add entries for all generations of this profile. + $conf .= "submenu \"$description\" {\n" if $grubVersion == 2; + + sub nrFromGen { my ($x) = @_; $x =~ /\/\w+-(\d+)-link/; return $1; } + + my @links = sort + { nrFromGen($b) <=> nrFromGen($a) } + (glob "$profile-*-link"); + + my $curEntry = 0; + foreach my $link (@links) { + last if $curEntry++ >= $configurationLimit; + my $date = strftime("%F", localtime(lstat($link)->mtime)); + my $version = + -e "$link/nixos-version" + ? readFile("$link/nixos-version") + : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); + addEntry("NixOS - Configuration " . nrFromGen($link) . " ($date - $version)", $link); + } + + $conf .= "}\n" if $grubVersion == 2; } -$conf .= "}\n" if $grubVersion == 2; +addProfile "/nix/var/nix/profiles/system", "NixOS - All configurations"; + +if ($grubVersion == 2) { + for my $profile (glob "/nix/var/nix/profiles/system-profiles/*") { + my $name = basename($profile); + next unless $name =~ /^\w+$/; + addProfile $profile, "NixOS - Profile '$name'"; + } +} # Run extraPrepareConfig in sh if ($extraPrepareConfig ne "") {