nix-config/pkgs/diff-flake/diff-flake

192 lines
5.4 KiB
Plaintext
Raw Normal View History

#!/usr/bin/env bash
set -eu
NEW_REV=
PREVIOUS_REV="$(git rev-parse @~)"
OUTPUT_FILE=/dev/stdout
FLAKE_OUTPUTS=()
NIX_BUILD_ARGS=()
print_err() {
printf "%s\n" "$1" >&2
}
sanitize_output() {
if [ "$OUTPUT_FILE" != "/dev/stdout" ]; then
sed 's/\x1b\[[0-9;]*m//g'
else
cat
fi
}
current_system() {
nix eval --raw --impure --expr 'builtins.currentSystem'
}
add_home() {
FLAKE_OUTPUTS+=("homeConfigurations.\"$1\".activationPackage")
}
add_host() {
FLAKE_OUTPUTS+=("nixosConfigurations.\"$1\".config.system.build.toplevel")
}
add_shell() {
# Use 'inputDerivation' attribute to make sure that it is build-able
FLAKE_OUTPUTS+=("devShells.\"$(current_system)\".\"$1\".inputDerivation")
}
usage() {
print_err "Usage: $0 [option]... [-- [nix build option]...]"
print_err ""
print_err " -h, --help"
print_err " print this usage screen and exit"
print_err " -f, --flake-output"
print_err " specify which flake output's closures should be diffed,"
print_err " can be used multiple times to specify multiple outputs"
print_err " -o, --output"
print_err " specify where to output the closure diffs,"
print_err " defaults to printing to standard output"
print_err " -n, --new-rev"
print_err " which git revision should be considered the 'new' state,"
print_err " defaults to current state"
print_err " -p, --previous-rev"
print_err " which git revision should be considered the 'previous' state,"
print_err " defaults to HEAD~"
print_err " --home [name]"
print_err " specify the name of a home-manager output configuration whose"
print_err " closure should be diffed, can be used multiple times"
print_err " if no configuration name is given, defaults to current username"
print_err " --host [name]"
print_err " specify the name of a NixOS output configuration whose"
print_err " closure should be diffed, can be used multiple times"
print_err " if no host name is given, defaults to current hostname"
print_err " --shell [name]"
print_err " specify a specific devShell configuration name whose closure"
print_err " should be diffed, can be used multiple times"
print_err " if no name is given, defaults to 'default'"
print_err ""
print_err "when no flake outputs are specified, automatically queries for"
print_err "all NixOS configurations, and devShells for current system"
}
is_option() {
[ $# -gt 0 ] && [[ $1 =~ ^(-.|--.*)$ ]]
}
parse_args() {
while [ $# -gt 0 ]; do
opt="$1"
shift
case "$opt" in
-h|--help)
usage
exit
;;
-f|--flake-output)
FLAKE_OUTPUTS+=("$1")
shift
;;
-o|--output)
OUTPUT_FILE="$1"
shift
;;
-n|--new-rev)
NEW_REV="$(git rev-parse "$1")"
shift
;;
-p|--previous-rev)
PREVIOUS_REV="$(git rev-parse "$1")"
shift
;;
--home)
if [ $# -gt 0 ] && ! is_option "$1"; then
add_home "$1"
shift
else
add_home "$USER"
fi
;;
--host)
if [ $# -gt 0 ] && ! is_option "$1"; then
add_host "$1"
shift
else
add_host "$(hostname)"
fi
;;
--shell)
if [ $# -gt 0 ] && ! is_option "$1"; then
add_shell "$1"
shift
else
add_shell "default"
fi
;;
--)
NIX_BUILD_ARGS=("$@")
break
;;
*)
print_err "Unknown argument '$opt'"
usage
exit 1
;;
esac
done
}
list_home_configurations() {
nix eval '.#homeConfigurations' \
--apply 'attrs: with builtins; concatStringsSep "\n" (attrNames attrs)' \
--raw
}
list_nixos_configurations() {
nix eval '.#nixosConfigurations' \
--apply 'attrs: with builtins; concatStringsSep "\n" (attrNames attrs)' \
--raw
}
list_dev_shells() {
nix eval ".#devShells.\"$(current_system)\"" \
--apply 'attrs: with builtins; concatStringsSep "\n" (attrNames attrs)' \
--raw
}
diff_output() {
local PREV NEW;
PREV="$(mktemp --dry-run)"
NEW="$(mktemp --dry-run)"
nix build "${NIX_BUILD_ARGS[@]}" ".?rev=${PREVIOUS_REV}#$1" -o "$PREV"
nix build "${NIX_BUILD_ARGS[@]}" ".${NEW_REV:+?rev=$NEW_REV}#$1" -o "$NEW"
{
# shellcheck disable=SC2016
printf 'Closure diff for `%s`:\n```\n' "$1"
nix store diff-closures "$PREV" "$NEW" | sanitize_output
printf '```\n\n'
} >> "$OUTPUT_FILE"
}
parse_args "$@"
if [ "${#FLAKE_OUTPUTS[@]}" -eq 0 ]; then
for home in $(list_home_configurations); do
add_home "$home"
done
for host in $(list_nixos_configurations); do
add_host "$host"
done
for shell in $(list_dev_shells); do
add_shell "$shell"
done
fi
for out in "${FLAKE_OUTPUTS[@]}"; do
diff_output "$out"
done