nixos-generators/nixos-generate
2022-05-17 22:47:23 +02:00

177 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
## Configuration
readonly libexec_dir="${0%/*}"
readonly format_dir=$libexec_dir/formats
configuration=${NIXOS_CONFIG:-$libexec_dir/configuration.nix}
flake_uri=
flake_attr=
format_path=
target_system=
cores=
run=
nix_args=(
"$libexec_dir/nixos-generate.nix"
)
has_outlink=false
nix_build_args=()
## Functions
showUsage() {
cat <<USAGE
Usage: $0 [options]
Options:
* --help: shows this help
* -c, --configuration PATH:
select the nixos configuration to build. Default: $configuration
* --flake URI:
selects the nixos configuration to build, using flake uri like "~/dotfiles#my-config"
* -f, --format NAME: select one of the pre-determined formats
* --format-path PATH: pass a custom format
* --list: list the available built-in formats
* --run: runs the configuration in a VM
only works for the "vm" and "vm-nogui" formats
* --show-trace: show more detailed nix evaluation location information
* --system: specify the target system (eg: x86_64-linux)
* -o, --out-link: specify the outlink location for nix-build
* --cores : to control the maximum amount of parallelism. (see nix-build documentation)
* --option : Passed to nix-build (see nix-build documentation).
* -I KEY=VALUE: Add a key to the Nix expression search path.
USAGE
}
listFormats() {
for format in "$format_dir"/*.nix; do
basename "$format" ".nix"
done
}
abort() {
echo "aborted: $*" >&2
exit 1
}
## Main ##
while [[ $# -gt 0 ]]; do
case "$1" in
-c | --configuration)
configuration=$2
shift
;;
--flake)
# Note: The reason I'm using awk over cut is because cutting with an
# out-of-bounds field will return the last in-bound field instead of empty
# string.
flake="$(echo "$2" | awk -F'#' '{ print $1; }')"
flake_uri="$(nix flake metadata --json -- "$flake" | jq -r .url)"
flake_attr="$(echo "$2" | awk -F'#' '{ print $2; }')"
shift
;;
--cores)
cores=$2
shift
;;
--option)
nix_build_args+=("$1" "$2" "$3")
shift 2
;;
-f | --format)
format_path=$format_dir/$2.nix
shift
;;
--format-path)
format_path=$2
shift
;;
--help)
showUsage
exit
;;
--list)
listFormats
exit
;;
--run)
run=1
# default to the VM format
if [[ -z $format_path ]]; then
format_path=$format_dir/vm.nix
fi
;;
--show-trace)
nix_args+=(--show-trace)
;;
--system)
target_system=$2
shift
;;
-I)
nix_args+=(-I "$2")
shift
;;
-o | --out-link)
nix_build_args+=(--out-link "$2")
has_outlink=true
shift
;;
*)
abort "unknown option $1"
;;
esac
shift
done
if ! $has_outlink; then
nix_build_args+=(--no-out-link)
fi
if [[ -z $format_path ]]; then
abort "missing format. use --help for more details"
fi
if [[ ! -f $format_path ]]; then
abort "format file not found: $format_path"
fi
nix_args+=(--argstr formatConfig "$(realpath "$format_path")")
if [[ -z "$flake_uri" ]]; then
nix_args+=(
-I "nixos-config=$configuration"
)
else
nix_args+=(
--argstr flakeUri "$flake_uri"
--argstr flakeAttr "${flake_attr:-"$(hostname)"}"
)
fi
if [[ -n $target_system ]]; then
nix_args+=(--argstr system "$target_system")
fi
if [[ -n $cores ]]; then
nix_args+=(--cores "$cores")
fi
formatAttr=$(nix-instantiate "${nix_args[@]}" --eval --json -A config.formatAttr | jq -r .)
filename=$(nix-instantiate "${nix_args[@]}" --eval --json -A config.filename | jq -r .)
out=$(nix-build "${nix_args[@]}" "${nix_build_args[@]}" -A "config.system.build.$formatAttr")
if [[ -z $run ]]; then
# show the first file, ignoring nix-support
find "$out" -wholename "$filename" -xtype f -print -quit
else
runner=$(find "$out"/bin -type l -print -quit)
exec "$runner"
fi