161 lines
4.4 KiB
Bash
Executable file
161 lines
4.4 KiB
Bash
Executable file
#!/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
|
|
}
|
|
|
|
add_shell() {
|
|
local SYSTEM
|
|
if [ $# -gt 0 ] && [ -n "$1" ]; then
|
|
SYSTEM="$1"
|
|
else
|
|
SYSTEM="$(nix eval --raw --impure --expr 'builtins.currentSystem')"
|
|
fi
|
|
# Use 'inputDerivation' attribute to make sure that it is build-able
|
|
FLAKE_OUTPUTS+=("devShells.$SYSTEM.default.inputDerivation")
|
|
}
|
|
|
|
add_host() {
|
|
FLAKE_OUTPUTS+=("nixosConfigurations.$1.config.system.build.toplevel")
|
|
}
|
|
|
|
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 " --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 [system]"
|
|
print_err " specify a specific system's devShell output whose closure"
|
|
print_err " should be diffed, can be used multiple times"
|
|
print_err " if no system is given, defaults to current system"
|
|
print_err ""
|
|
print_err "when no flake outputs are specified, automatically queries for"
|
|
print_err "all NixOS configurations, and devShell 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
|
|
;;
|
|
--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
|
|
fi
|
|
;;
|
|
--)
|
|
NIX_BUILD_ARGS=("$@")
|
|
break
|
|
;;
|
|
*)
|
|
print_err "Unknown argument '$opt'"
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
list_nixos_configurations() {
|
|
nix eval '.#nixosConfigurations' \
|
|
--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 host in $(list_nixos_configurations); do
|
|
add_host "$host"
|
|
done
|
|
add_shell
|
|
fi
|
|
|
|
for out in "${FLAKE_OUTPUTS[@]}"; do
|
|
diff_output "$out"
|
|
done
|