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.
This commit is contained in:
Robert Hensing 2023-07-09 23:04:27 +02:00
parent 584463c744
commit 0e062cb692
3 changed files with 76 additions and 2 deletions

View file

@ -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

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 | 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

View file

@ -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 '<nixpkgs/nixos>' "${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"