nixos-rebuild-ng: add --diff argument (#489208)
This commit is contained in:
@@ -308,6 +308,14 @@ It must be one of the following:
|
||||
option, it is possible to build non-flake NixOS configurations even if
|
||||
the current NixOS systems uses flakes.
|
||||
|
||||
*--diff*
|
||||
show the diff between the system closure in /run/current-system
|
||||
and the newly built system closure.
|
||||
(avaliable for actions: build, boot, test, switch)
|
||||
|
||||
This is similar to running:
|
||||
"nix store diff-closures /run/current-system result" after build
|
||||
|
||||
In addition, *nixos-rebuild* accepts following options from nix commands that
|
||||
the tool calls:
|
||||
|
||||
|
||||
@@ -197,6 +197,12 @@ def get_parser() -> tuple[argparse.ArgumentParser, dict[str, argparse.ArgumentPa
|
||||
help="Selects an image variant to build from the "
|
||||
"config.system.build.images attribute of the given configuration",
|
||||
)
|
||||
main_parser.add_argument(
|
||||
"--diff",
|
||||
action="store_true",
|
||||
help="prints out the diff between the current system "
|
||||
"and the newly built one using nix store diff-closures"
|
||||
)
|
||||
main_parser.add_argument("action", choices=Action.values(), nargs="?")
|
||||
|
||||
return main_parser, sub_parsers
|
||||
@@ -259,6 +265,20 @@ def parse_args(
|
||||
if args.no_build_nix:
|
||||
parser_warn("--no-build-nix is deprecated, we do not build nix anymore")
|
||||
|
||||
if args.diff and args.action not in (
|
||||
# case for calling build_and_activate_system
|
||||
# except excluding DRY_BUILD and DRY_ACTIVATE,
|
||||
# in which --diff is uniquely a no-op
|
||||
Action.SWITCH.value,
|
||||
Action.BOOT.value,
|
||||
Action.TEST.value,
|
||||
Action.BUILD.value,
|
||||
Action.BUILD_IMAGE.value,
|
||||
Action.BUILD_VM.value,
|
||||
Action.BUILD_VM_WITH_BOOTLOADER.value,
|
||||
):
|
||||
parser_warn(f"--diff is a no-op with '{args.action}'")
|
||||
|
||||
if args.action == Action.EDIT.value and (args.file or args.attr):
|
||||
parser.error("--file and --attr are not supported with 'edit'")
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import sys
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
@@ -537,6 +538,25 @@ def list_generations(profile: Profile) -> list[GenerationJson]:
|
||||
reverse=True,
|
||||
)
|
||||
|
||||
def diff_closures(current_config: Path, new_config: Path, target_host: Remote | None = None):
|
||||
print(
|
||||
f"<<< {current_config}\n"
|
||||
f">>> {new_config}",
|
||||
file=sys.stderr
|
||||
)
|
||||
run_wrapper(
|
||||
[
|
||||
"nix",
|
||||
*FLAKE_FLAGS,
|
||||
"store",
|
||||
"diff-closures",
|
||||
current_config,
|
||||
new_config,
|
||||
],
|
||||
remote=target_host,
|
||||
stdout=sys.stderr
|
||||
)
|
||||
|
||||
|
||||
def repl(build_attr: BuildAttr, nix_flags: Args | None = None) -> None:
|
||||
run_args = ["nix", "repl", "--file", build_attr.path]
|
||||
|
||||
@@ -321,6 +321,13 @@ def build_and_activate_system(
|
||||
grouped_nix_args=grouped_nix_args,
|
||||
)
|
||||
|
||||
current_config = Path("/run/current-system")
|
||||
if args.diff:
|
||||
if current_config.exists():
|
||||
nix.diff_closures(current_config=current_config.readlink(), new_config=path_to_config, target_host=target_host)
|
||||
else:
|
||||
logger.warning(f"missing '{str(current_config)}', skipping configuration diff...")
|
||||
|
||||
_activate_system(
|
||||
path_to_config=path_to_config,
|
||||
action=action,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import sys
|
||||
import textwrap
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
@@ -550,6 +551,29 @@ def test_list_generations(mock_get_generations: Mock, tmp_path: Path) -> None:
|
||||
]
|
||||
|
||||
|
||||
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
|
||||
def test_diff_closures(mock_run: Mock) -> None:
|
||||
|
||||
assert n.diff_closures(
|
||||
Path("/run/current-system"),
|
||||
Path("/nix/var/nix/profiles/system"),
|
||||
None
|
||||
) == None
|
||||
mock_run.assert_called_with(
|
||||
[
|
||||
"nix",
|
||||
"--extra-experimental-features",
|
||||
"nix-command flakes",
|
||||
"store",
|
||||
"diff-closures",
|
||||
Path("/run/current-system"),
|
||||
Path("/nix/var/nix/profiles/system"),
|
||||
],
|
||||
remote=None,
|
||||
stdout=sys.stderr
|
||||
)
|
||||
|
||||
|
||||
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
|
||||
def test_repl(mock_run: Mock) -> None:
|
||||
n.repl(m.BuildAttr("<nixpkgs/nixos>", None), {"nix_flag": True})
|
||||
|
||||
Reference in New Issue
Block a user