84 lines
3.3 KiB
Nix
84 lines
3.3 KiB
Nix
# `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 ];
|
|
};
|
|
}
|