#!/usr/bin/env bash set -euo pipefail log_info(){ echo "[INFO] $(date -Iseconds) $*"; } log_warn(){ echo "[WARN] $(date -Iseconds) $*" >&2; } log_error(){ echo "[ERROR] $(date -Iseconds) $*" >&2; } die(){ log_error "$*"; exit 1; } need(){ command -v "$1" >/dev/null 2>&1 || die "Missing required tool: $1"; } confirm_gate() { : "${DRY_RUN:=1}" : "${REQUIRE_CONFIRM:=1}" : "${CONFIRM_PHRASE:=I UNDERSTAND THIS WILL HASH FILES AND EMIT A ROOT}" [[ "$DRY_RUN" == "0" ]] || die "DRY_RUN=$DRY_RUN (set DRY_RUN=0)." if [[ "$REQUIRE_CONFIRM" == "1" ]]; then echo "Type to confirm:" echo " $CONFIRM_PHRASE" read -r input [[ "$input" == "$CONFIRM_PHRASE" ]] || die "Confirmation phrase mismatch." fi } pick_hasher() { if command -v b3sum >/dev/null 2>&1; then echo "b3sum" elif command -v blake3 >/dev/null 2>&1; then echo "blake3" else die "Need b3sum or blake3 installed." fi } hash_file() { local hasher="$1" file="$2" if [[ "$hasher" == "b3sum" ]]; then b3sum "$file" | awk '{print $1}' else blake3 "$file" | awk '{print $1}' fi } hash_pair_hex() { local hasher="$1" left="$2" right="$3" local tmp; tmp="$(mktemp)" printf "%s%s" "$left" "$right" > "$tmp" local h if [[ "$hasher" == "b3sum" ]]; then h="$(b3sum "$tmp" | awk '{print $1}')" else h="$(blake3 "$tmp" | awk '{print $1}')" fi rm -f "$tmp" printf "%s" "$h" } json_escape() { local s="$1" s="${s//\\/\\\\}"; s="${s//\"/\\\"}"; s="${s//$'\n'/\\n}" printf "%s" "$s" }