#!/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 <&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 ;; --disk-size) nix_build_args+=("--argstr" "diskSize" "$2") shift ;; --special-arg) nix_build_args+=("--argstr" "$2" "$3") shift 2 ;; --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-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 .) fileExtension=$(nix-instantiate "${nix_args[@]}" --eval --json -A config.fileExtension | jq -r .) out=$(nix build --extra-experimental-features nix-command -L --print-out-paths --file "${nix_args[@]}" "${nix_build_args[@]}" "config.system.build.$formatAttr") if [[ -z $run ]]; then # show the first file, ignoring nix-support find "$out" -name "*$fileExtension" -xtype f -print -quit else runner=$(find "$out"/bin -type l -print -quit) exec "$runner" fi