#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")" cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-} check_args=("$@") if [[ "${1:-}" == "--cache-dir" ]]; then if [[ "$#" -lt 2 ]]; then echo "missing --cache-dir value" >&2 exit 1 fi cache_dir=$2 shift 2 check_args=("$@") fi manifest=${1:-} require_complete=${2:-} linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc} if [[ -z "$cache_dir" ]]; then LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}" exit 0 fi if [[ "$cache_dir" =~ [[:space:]] ]]; then echo "CNC_SIM_PREFLIGHT_CACHE_DIR must not contain whitespace: $cache_dir" >&2 exit 1 fi mkdir -p "$cache_dir" cache_dir=$(cd "$cache_dir" && pwd) if [[ "$cache_dir" == "/" ]]; then echo "CNC_SIM_PREFLIGHT_CACHE_DIR must not be the filesystem root" >&2 exit 1 fi exec 8>"$cache_dir/check-linuxcnc-inputs.lock" flock 8 if [[ ! -d "$linuxcnc_root" ]]; then LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}" exit 0 fi linuxcnc_root=$(cd "$linuxcnc_root" && pwd) manifest_key=ROOT_ONLY manifest_path= if [[ -n "$manifest" && "$manifest" != "--root-only" ]]; then if [[ ! -f "$manifest" ]]; then LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}" exit 0 fi manifest_path=$(cd "$(dirname "$manifest")" && pwd)/$(basename "$manifest") manifest_key=$(printf '%s' "$manifest_path" | sha256sum | awk '{ print $1 }') fi safe_require=${require_complete:-none} safe_require=${safe_require//[^A-Za-z0-9_.-]/_} args_key=$( { printf 'ARGS=' printf ' %q' "${check_args[@]}" printf '\n' } | sha256sum | awk '{ print $1 }' ) cache_file="$cache_dir/check-linuxcnc-inputs.${manifest_key}.${safe_require}.${args_key}.signature" next_signature=$(mktemp "$cache_file.next.XXXXXX") write_source_stat_signature() { local source_path [[ -z "$manifest_path" ]] && return 0 while IFS=: read -r group path note extra; do case "$group" in ""|\#*) continue ;; esac [[ -z "${path:-}" ]] && continue source_path="$linuxcnc_root/$path" if [[ ! -f "$source_path" ]]; then return 1 fi stat -c 'SOURCE=%n:%s:%y' "$source_path" done < "$manifest_path" } write_complete_mode_signature() { case "$require_complete" in --require-rs274-complete) find "$linuxcnc_root/src/emc/rs274ngc" -maxdepth 1 -type f \ -printf 'RS274=%P:%s:%T@\n' | sort ;; --require-kinematics-complete) for source_dir in \ "$linuxcnc_root/src/emc/kinematics" \ "$linuxcnc_root/src/libnml/posemath" \ "$linuxcnc_root/configs/sim"; do [[ -d "$source_dir" ]] || return 1 find "$source_dir" -type f -printf "KIN=$source_dir/%P:%s:%T@\n" | sort done ;; esac } if ! { printf 'CHECK_SCRIPT=' sha256sum check-linuxcnc-inputs.sh printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root" printf 'ARGS=' printf ' %q' "${check_args[@]}" printf '\n' if [[ -n "$manifest_path" ]]; then printf 'MANIFEST_PATH=%s\n' "$manifest_path" printf 'MANIFEST=' sha256sum "$manifest_path" write_source_stat_signature fi write_complete_mode_signature } > "$next_signature"; then rm -f "$next_signature" LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}" exit 0 fi if [[ -f "$cache_file" ]] && cmp -s "$cache_file" "$next_signature"; then rm -f "$next_signature" exit 0 fi LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}" mv "$next_signature" "$cache_file"