From 0e062cb692c3f28c4d5c5a60e30aedc8816e2924 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 9 Jul 2023 23:04:27 +0200 Subject: [PATCH] nixos-rebuild: Add nixos-rebuild repl Apologies to the non-flake users; your repl isn't quite as fancy, but at least evaluates your config exactly as you would expect, unlike flakes which are only evaluated impurely for now. --- .../installation/changing-config.chapter.md | 8 +++ .../linux/nixos-rebuild/nixos-rebuild.8 | 6 +- .../linux/nixos-rebuild/nixos-rebuild.sh | 64 ++++++++++++++++++- 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/nixos/doc/manual/installation/changing-config.chapter.md b/nixos/doc/manual/installation/changing-config.chapter.md index 12abf90b718f..9e56b15a880f 100644 --- a/nixos/doc/manual/installation/changing-config.chapter.md +++ b/nixos/doc/manual/installation/changing-config.chapter.md @@ -55,6 +55,14 @@ which causes the new configuration (and previous ones created using This can be useful to separate test configurations from "stable" configurations. +A repl, or read-eval-print loop, is also available. You can inspect your configuration and use the Nix language with + +```ShellSession +# nixos-rebuild repl +``` + +Your configuration is loaded into the `config` variable. Use tab for autocompletion, use the `:r` command to reload the configuration files. See `:?` or [`nix repl` in the Nix manual](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-repl.html) to learn more. + Finally, you can do ```ShellSession diff --git a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.8 b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.8 index 124c01046ea3..47ffd20740f6 100644 --- a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.8 +++ b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.8 @@ -10,7 +10,7 @@ .Sh SYNOPSIS .Nm .Bro -.Cm switch | boot | test | build | dry-build | dry-activate | edit | build-vm | build-vm-with-bootloader | list-generations Op Fl -json +.Cm switch | boot | test | build | dry-build | dry-activate | edit | repl | build-vm | build-vm-with-bootloader | list-generations Op Fl -json .Brc .br .Op Fl -upgrade | -upgrade-all @@ -143,6 +143,10 @@ Opens .Pa configuration.nix in the default editor. . +.It Cm repl +Opens the configuration in +.Ic nix repl Ns . +. .It Cm build-vm Build a script that starts a NixOS virtual machine with the desired configuration. It leaves a symlink diff --git a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh index dddae8da2068..1748236369e8 100755 --- a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh +++ b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh @@ -49,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|list-generations) + switch|boot|test|build|edit|repl|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 @@ -511,6 +511,68 @@ if [ "$action" = dry-build ]; then extraBuildFlags+=(--dry-run) fi +if [ "$action" = repl ]; then + # This is a very end user command, implemented using sub-optimal means. + # You should feel free to improve its behavior, as well as resolve tech + # debt in "breaking" ways. Humans adapt quite well. + if [[ -z $flake ]]; then + exec nix repl '' "${extraBuildFlags[@]}" + else + if [[ -n "${lockFlags[0]}" ]]; then + # nix repl itself does not support locking flags + log "nixos-rebuild repl does not support locking flags yet" + exit 1 + fi + d='$' + q='"' + bold="$(echo -e '\033[1m')" + blue="$(echo -e '\033[34;1m')" + attention="$(echo -e '\033[35;1m')" + reset="$(echo -e '\033[0m')" + # This nix repl invocation is impure, because usually the flakeref is. + # For a solution that preserves the motd and custom scope, we need + # something like https://github.com/NixOS/nix/issues/8679. + exec nix repl --impure --expr " + let flake = builtins.getFlake ''$flake''; + configuration = flake.$flakeAttr; + motd = '' + $d{$q\n$q} + Hello and welcome to the NixOS configuration + $flakeAttr + in $flake + + The following is loaded into nix repl's scope: + + - ${blue}config${reset} All option values + - ${blue}options${reset} Option data and metadata + - ${blue}pkgs${reset} Nixpkgs package set + - other module arguments + + - ${blue}flake${reset} Flake outputs, inputs and source info of $flake + + Use tab completion to browse around ${blue}config${reset}. + + Use ${bold}:r${reset} to ${bold}reload${reset} everything after making a change in the flake. + (assuming $flake is a mutable flake ref) + + See ${bold}:?${reset} for more repl commands. + + ${attention}warning:${reset} nixos-rebuild repl does not currently enforce pure evaluation. + ''; + scope = + assert configuration._type or null == ''configuration''; + assert configuration.class or ''nixos'' == ''nixos''; + configuration._module.args // + configuration._module.specialArgs // + { + inherit (configuration) config options; + inherit flake; + }; + in builtins.seq scope builtins.trace motd scope + " "${extraBuildFlags[@]}" + fi +fi + if [ "$action" = list-generations ]; then if [ ! -L "$profile" ]; then log "No profile \`$(basename "$profile")' found"