feat(nixos): add nixos-diff rebuild diff + reboot/re-login helper
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# `nixos-diff`: after a rebuild, report (1) what packages changed and (2) whether the
|
||||
# change needs a reboot, a re-login, or nothing. NixOS keeps two markers —
|
||||
# /run/booted-system (what you booted) and /run/current-system (what the last `switch`
|
||||
# activated). A switch applies userland live, but:
|
||||
# - the kernel, initrd, and kernel modules are frozen until the next BOOT — detected
|
||||
# exactly, by comparing those store paths between the two systems;
|
||||
# - session-mapped components (the Wayland compositor, GL stack, portals) a running
|
||||
# graphical session keeps until you log out and back in — detected HEURISTICALLY,
|
||||
# by matching changed package names against `local.rebuildDiff.reloginPackages`.
|
||||
# Generic and topology-free, so it rides in the baseline; disable with
|
||||
# `local.rebuildDiff.enable = false`.
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.local.rebuildDiff;
|
||||
reloginPattern = lib.concatStringsSep "|" cfg.reloginPackages;
|
||||
|
||||
nixos-diff = pkgs.writeShellApplication {
|
||||
name = "nixos-diff";
|
||||
runtimeInputs = [ pkgs.nvd pkgs.coreutils pkgs.gnugrep ];
|
||||
text = ''
|
||||
booted=/run/booted-system
|
||||
current=/run/current-system
|
||||
|
||||
# Package-level diff of the running system vs the activated one. Force colour
|
||||
# (nvd auto-disables it when captured); only version parts are coloured, so the
|
||||
# package-name grep below is unaffected.
|
||||
diff=$(nvd --color always diff "$booted" "$current")
|
||||
printf '%s\n' "$diff"
|
||||
|
||||
# Reboot (exact): kernel/initrd/modules only take effect on the next boot.
|
||||
reboot=0
|
||||
for c in kernel initrd kernel-modules; do
|
||||
[ "$(readlink -f "$booted/$c" 2>/dev/null)" = "$(readlink -f "$current/$c" 2>/dev/null)" ] \
|
||||
|| reboot=1
|
||||
done
|
||||
|
||||
# Re-login (heuristic): session-mapped components a running Wayland session
|
||||
# keeps until you log out and back in.
|
||||
relogin_hits=""
|
||||
${lib.optionalString (reloginPattern != "") ''
|
||||
relogin_hits=$(printf '%s\n' "$diff" | grep -Ew "${reloginPattern}" || true)
|
||||
''}
|
||||
|
||||
echo
|
||||
if [ "$reboot" -eq 1 ]; then
|
||||
printf '>>> REBOOT needed (kernel/initrd/modules changed).\n'
|
||||
elif [ -n "$relogin_hits" ]; then
|
||||
printf '>>> RE-LOGIN recommended — session components changed:\n'
|
||||
printf '%s\n' "$relogin_hits"
|
||||
else
|
||||
printf '>>> No reboot/re-login needed.\n'
|
||||
fi
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
options.local.rebuildDiff = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Install `nixos-diff`: after a `nixos-rebuild switch`, print an `nvd` closure
|
||||
diff of the running vs activated system plus a reboot / re-login / live verdict.
|
||||
'';
|
||||
};
|
||||
|
||||
reloginPackages = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ "mesa" "wayland" "hyprland" "xdg-desktop-portal" ];
|
||||
description = ''
|
||||
Whole-word package-name patterns matched against the diff; a match means a
|
||||
running Wayland session should be restarted (re-login) to pick the change up —
|
||||
the compositor, GL stack, and portals. Extend per host (e.g. a specific GPU
|
||||
driver). Empty disables the re-login heuristic.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ nixos-diff pkgs.nvd ];
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user