#!/usr/bin/env bash

set -euo pipefail

toplevel="$(git rev-parse --show-toplevel)"

# Build and cache the specified arguments
just() {
    if command -v nom &> /dev/null; then
        nom build "$@"
    else
        nix build "$@"
    fi

    if [ -z ${ATTIC_TOKEN+x} ]; then
        echo "\$ATTIC_TOKEN is unset, skipping uploading to the binary cache"
        return
    fi

    nix run --inputs-from "$toplevel" attic -- \
        login \
        "$ATTIC_SERVER" \
        "$ATTIC_ENDPOINT" \
        "$ATTIC_TOKEN"

    # Find all output paths of the installables and their build dependencies
    readarray -t derivations < <(nix path-info --derivation "$@")
    cache=()
    for derivation in "${derivations[@]}"; do
        cache+=(
            "$(nix-store --query --requisites --include-outputs "$derivation")"
        )
    done

    # Upload them to Attic
    #
    # Use `xargs` and a here-string because something would probably explode if
    # several thousand arguments got passed to a command at once. Hopefully no
    # store paths include a newline in them.
    (
        IFS=$'\n'
        nix shell --inputs-from "$toplevel" attic -c xargs \
            attic push "$ATTIC_SERVER:$ATTIC_CACHE" <<< "${cache[*]}"
    )
}

# Build and cache things needed for CI
ci() {
    cache=(
        --inputs-from "$toplevel"

        # Keep sorted
        "$toplevel#devShells.x86_64-linux.default"
        "$toplevel#devShells.x86_64-linux.all-features"
        attic#default
        nixpkgs#direnv
        nixpkgs#jq
        nixpkgs#nix-direnv
    )

    just "${cache[@]}"
}

# Build and cache all the package outputs
packages() {
    declare -a cache="($(
        nix flake show --json 2> /dev/null |
            nix run --inputs-from "$toplevel" nixpkgs#jq -- \
            -r \
            '.packages."x86_64-linux" | keys | map("'"$toplevel"'#" + .) | @sh'
    ))"

    just "${cache[@]}"
}

eval "$@"
