Scripts to (interactively) demonstrate capabilities of Nix. Mirror of https://gitlab.com/SFrijters/nix-container-demo
# -*- sh-shell: bash -*-
# shellcheck shell=bash
if [ -z ${_NIX_CONTAINER_DEMO_HELPER_INC+x} ]; then
    _NIX_CONTAINER_DEMO_HELPER_INC=true

    source "$(dirname "${BASH_SOURCE[0]}")/../libdemo/libdemo.sh"

    export NIXPKGS_FLAKEREF=github:nixos/nixpkgs/1d56444d15859eb2e1c929c375a019616af2b59f

    bat() {
        if __libdemo_use_colour; then
            nix run "${NIXPKGS_FLAKEREF}#bat" -- --pager none --decorations always --color=always "$@"
        else
            while [ $# -gt 1 ]; do
                shift
            done
            nix run "${NIXPKGS_FLAKEREF}#bat" -- --pager none --decorations always "$@"
        fi
    }

    tiv() {
        if __libdemo_use_colour; then
            nix run "${NIXPKGS_FLAKEREF}#tiv" -- "$@"
        else
            echo "no colour output available, use your imagination!"
        fi
    }

    file() {
        nix run "${NIXPKGS_FLAKEREF}#file" -- "$@"
    }

    __nix_gcroot_local_dir="$(dirname "${BASH_SOURCE[0]}")/../gcroots"
    __nix_gcroot_store_dir="/nix/var/nix/gcroots/per-user/${USER}"
    __nix_gcroot_prefix=nix-container-demo

    __nix_make_gcroot() {
        if [ "${WRAP_NIX_MAKE_GCROOTS:-0}" = 1 ]; then
            local -r storepath="${1}"
            local -r suffix="$(basename "${storepath}")"
            if __libdemo_use_colour; then
                echo -e "\e[0;37mPreventing GC for '${storepath}'\e[0m"
            else
                echo "Preventing GC for '${storepath}'"
            fi
            mkdir -p "${__nix_gcroot_local_dir}"
            local -r gcroot_local="$(realpath --no-symlinks "${__nix_gcroot_local_dir}/${__nix_gcroot_prefix}-${suffix}")"
            rm -f "${gcroot_local}"
            ln -s "${storepath}" "${gcroot_local}"
            local -r gcroot_store="${__nix_gcroot_store_dir}/${__nix_gcroot_prefix}-${suffix}"
            rm -f "${gcroot_store}"
            ln -s "${gcroot_local}" "${gcroot_store}"
        fi
    }

    __nix_print_gcroots() {
        echo "Printing existing GC roots"
        find "${__nix_gcroot_store_dir}" -name "${__nix_gcroot_prefix}-*" -print | sed "s|${__nix_gcroot_store_dir}/||"
    }

    __nix_clean_gcroots() {
        __nix_print_gcroots
        echo "Removing existing GC roots"
        find "${__nix_gcroot_store_dir}" -name "${__nix_gcroot_prefix}-*" -delete
    }

    # Wrapper for the nix executable to help with interactive demos and gc roots
    # - If WRAP_NIX_MAKE_GCROOTS=1 the nix (build|develop|run) commands will add gc roots for their outputs
    # - In interactive mode, nix build commands will be run with --rebuild for demonstration purposes, if its output already exists
    # Assumptions: invocation is of the form 'nix <action> <flake output> ...'.
    nix() {
        local -r action=$1
        shift

        local nix_args=()
        local args=()

        # Separate arguments for nix from arguments passed through to another command, separated by '--'
        local __encountered_dashes=0
        while [ $# -gt 0 ]; do
            if [ "$1" == "--" ]; then
                __encountered_dashes=1
            elif [ "${__encountered_dashes}" = 1 ]; then
                args+=("$1")
            else
                nix_args+=("$1")
            fi
            shift
        done

        # Custom actions for nix run, build, and develop commands
        local storepath
        if [ "${action}" = run ]; then
            command nix run "${nix_args[@]}" -- "${args[@]}"
            for storepath in $(command nix build "${nix_args[@]}" --no-link --print-out-paths); do
                __nix_make_gcroot "${storepath}"
            done
        elif [ "${action}" = build ]; then
            if __libdemo_is_interactive && [ -e "$(nix eval --raw "${nix_args[0]}")" ]; then
                command nix build "${nix_args[@]}" --rebuild
            else
                command nix build "${nix_args[@]}"
            fi
            for storepath in $(command nix build "${nix_args[@]}" --no-link --print-out-paths); do
                __nix_make_gcroot "${storepath}"
            done
        elif [ "${action}" = develop ]; then
            # shellcheck disable=SC2016
            storepath="$(command nix develop "${nix_args[0]}" --command bash -c 'echo ${NIX_GCROOT}' 2>/dev/null)"
            __nix_make_gcroot "${storepath}"
            command nix develop "${nix_args[@]}"
        else
            command nix "${action}" "${nix_args[@]}"
        fi
    }
fi