mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-04-16 21:38:18 +00:00
nixos-rebuild-ng: add repl
This commit is contained in:
parent
d325edd627
commit
88b4eb3aeb
@ -126,7 +126,7 @@ ruff format .
|
||||
- [ ] Change module system to allow easier opt-in, like
|
||||
`system.switch.enableNg` for `switch-to-configuration-ng`
|
||||
- [ ] Improve documentation
|
||||
- [ ] `nixos-rebuild repl` (calling old `nixos-rebuild` for now)
|
||||
- [x] `nixos-rebuild repl`
|
||||
- [ ] `nix` build/bootstrap
|
||||
- [ ] Generate tab completion via [`shtab`](https://docs.iterative.ai/shtab/)
|
||||
- [x] Reduce build closure
|
||||
|
@ -39,11 +39,6 @@ python3Packages.buildPythonApplication rec {
|
||||
nix
|
||||
];
|
||||
|
||||
preBuild = ''
|
||||
substituteInPlace nixos_rebuild/__init__.py \
|
||||
--subst-var-by nixos_rebuild ${lib.getExe nixos-rebuild}
|
||||
'';
|
||||
|
||||
postInstall =
|
||||
''
|
||||
installManPage ${nixos-rebuild}/share/man/man8/nixos-rebuild.8
|
||||
|
@ -1,7 +1,6 @@
|
||||
import argparse
|
||||
import atexit
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from subprocess import run
|
||||
|
@ -1,6 +1,8 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
from importlib.resources import files
|
||||
from pathlib import Path
|
||||
from string import Template
|
||||
from subprocess import PIPE, CalledProcessError
|
||||
from typing import Final
|
||||
|
||||
@ -18,6 +20,7 @@ from .process import run_wrapper
|
||||
from .utils import Args, dict_to_flags, info
|
||||
|
||||
FLAKE_FLAGS: Final = ["--extra-experimental-features", "nix-command flakes"]
|
||||
FLAKE_REPL_TEMPLATE: Final = "repl.template.nix"
|
||||
|
||||
|
||||
def copy_closure(
|
||||
@ -279,6 +282,41 @@ def nixos_build_flake(
|
||||
return Path(r.stdout.strip())
|
||||
|
||||
|
||||
def repl(attr: str, build_attr: BuildAttr | None, **nix_flags: Args) -> None:
|
||||
run_args: list[str | Path] = ["nix", "repl", "--file"]
|
||||
if build_attr:
|
||||
run_args.append(build_attr.path)
|
||||
if build_attr.attr:
|
||||
run_args.append(build_attr.attr)
|
||||
run_wrapper([*run_args, *dict_to_flags(nix_flags)])
|
||||
else:
|
||||
run_wrapper([*run_args, "<nixpkgs/nixos>", *dict_to_flags(nix_flags)])
|
||||
|
||||
|
||||
def repl_flake(attr: str, flake: Flake, **flake_flags: Args) -> None:
|
||||
expr = Template(
|
||||
files(__package__).joinpath(FLAKE_REPL_TEMPLATE).read_text()
|
||||
).substitute(
|
||||
flake_path=flake.path,
|
||||
flake_attr=flake.attr,
|
||||
bold="\033[1m",
|
||||
blue="\033[34;1m",
|
||||
attention="\033[35;1m",
|
||||
reset="\033[0m",
|
||||
)
|
||||
run_wrapper(
|
||||
[
|
||||
"nix",
|
||||
*FLAKE_FLAGS,
|
||||
"repl",
|
||||
"--impure",
|
||||
"--expr",
|
||||
expr,
|
||||
*dict_to_flags(flake_flags),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def rollback(profile: Profile, target_host: Remote | None, sudo: bool) -> Path:
|
||||
"Rollback Nix profile, like one created by `nixos-rebuild switch`."
|
||||
run_wrapper(
|
||||
|
@ -0,0 +1,40 @@
|
||||
let
|
||||
flake = builtins.getFlake ''${flake_path}'';
|
||||
configuration = flake.${flake_attr};
|
||||
motd = ''
|
||||
$${"\n"}
|
||||
Hello and welcome to the NixOS configuration
|
||||
${flake_attr}
|
||||
in ${flake_path}
|
||||
|
||||
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
|
||||
- ${blue}lib${reset} Nixpkgs library functions
|
||||
- other module arguments
|
||||
|
||||
- ${blue}flake${reset} Flake outputs, inputs and source info of ${flake_path}
|
||||
|
||||
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_path} 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;
|
||||
lib = configuration.lib or configuration.pkgs.lib;
|
||||
inherit flake;
|
||||
};
|
||||
in
|
||||
builtins.seq scope builtins.trace motd scope
|
@ -9,6 +9,9 @@ version = "0.0.0"
|
||||
[project.scripts]
|
||||
nixos-rebuild = "nixos_rebuild:main"
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
nixos_rebuild = ["*.template.nix"]
|
||||
|
||||
[tool.mypy]
|
||||
# `--strict` config, but explicit options to avoid breaking build when mypy is
|
||||
# updated
|
||||
|
@ -17,9 +17,7 @@ def test_building_attr_from_arg() -> None:
|
||||
assert m.BuildAttr.from_arg("attr", "file.nix") == m.BuildAttr(
|
||||
Path("file.nix"), "attr"
|
||||
)
|
||||
assert m.BuildAttr.from_arg(None, "file.nix") == m.BuildAttr(
|
||||
Path("file.nix"), None
|
||||
)
|
||||
assert m.BuildAttr.from_arg(None, "file.nix") == m.BuildAttr(Path("file.nix"), None)
|
||||
|
||||
|
||||
def test_flake_parse() -> None:
|
||||
|
@ -248,6 +248,25 @@ def test_nixos_build(mock_run: Any, monkeypatch: Any) -> None:
|
||||
)
|
||||
|
||||
|
||||
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
|
||||
def test_repl(mock_run: Any) -> None:
|
||||
n.repl("attr", None, nix_flag=True)
|
||||
mock_run.assert_called_with(
|
||||
["nix", "repl", "--file", "<nixpkgs/nixos>", "--nix-flag"]
|
||||
)
|
||||
|
||||
n.repl("attr", m.BuildAttr(Path("file.nix"), "myAttr"))
|
||||
mock_run.assert_called_with(["nix", "repl", "--file", Path("file.nix"), "myAttr"])
|
||||
|
||||
|
||||
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
|
||||
def test_repl_flake(mock_run: Any) -> None:
|
||||
n.repl_flake("attr", m.Flake(Path("flake.nix"), "myAttr"), nix_flag=True)
|
||||
# This method would be really annoying to test, and it is not that important
|
||||
# So just check that we are at least calling it
|
||||
assert mock_run.called
|
||||
|
||||
|
||||
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
|
||||
def test_rollback(mock_run: Any, tmp_path: Path) -> None:
|
||||
path = tmp_path / "test"
|
||||
|
Loading…
Reference in New Issue
Block a user