#!/usr/bin/env bash set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" project_root="$(git -C "$script_dir" rev-parse --show-toplevel)" if [[ -t 1 ]]; then c_reset=$'\033[0m' c_red=$'\033[31m' c_green=$'\033[32m' c_yellow=$'\033[33m' else c_reset='' c_red='' c_green='' c_yellow='' fi ok() { printf '%sOK%s: %s\n' "$c_green" "$c_reset" "$*"; } warn() { printf '%sWARN%s: %s\n' "$c_yellow" "$c_reset" "$*"; } fail() { printf '%sFAIL%s: %s\n' "$c_red" "$c_reset" "$*" >&2; } usage() { cat </dev/null || true) if [[ -z "$canonical" ]]; then canonical="$(python3 - <<'PY' "$project_root" "$linkpath" "$target" import os, sys root, linkpath, target = sys.argv[1:4] print(os.path.normpath(os.path.join(os.path.dirname(os.path.join(root, linkpath)), target))) PY )" fi if [[ "$canonical" == "$project_root/local/recipes/"* ]]; then classification="stale recipe overlay" action="recreate or refresh the overlay under local/recipes/" elif [[ "$canonical" == "$project_root/local/patches/"* ]]; then classification="stale patch symlink" action="restore the patch file and rewire the recipe symlink" elif [[ "$canonical" == "$project_root/local/sources/"* ]]; then classification="stale fork symlink" action="restore the local fork source tree" else classification="stale symlink (unclassified)" action="inspect the target and repair the symlink" fi if [[ ! -e "$project_root/$linkpath" ]]; then printf '%s%s:1%s target=%s class=%s action=%s\n' "$c_red" "$linkpath" "$c_reset" "$target" "$classification" "$action" case "$classification" in "stale recipe overlay") (( stale_recipe_overlay++ )) ;; "stale patch symlink") (( stale_patch_symlink++ )) ;; "stale fork symlink") (( stale_fork_symlink++ )) ;; *) (( stale_unclassified++ )) ;; esac (( broken++ )) fi done < <(find "$project_root/recipes" -type l ! -exec test -e {} \; -print | sed "s#^$project_root/##") while IFS= read -r linkpath; do [[ -n "$linkpath" ]] || continue if [[ ! -e "$project_root/$linkpath" ]]; then printf '%s%s:1%s target=%s class=%s action=update submodule path or initialize submodule\n' "$c_red" "$linkpath" "$c_reset" "missing" "missing submodule path" (( stale_submodule++ )) (( broken++ )) fi (( gitlink_count++ )) done < <(git -C "$project_root" ls-tree -r --full-tree HEAD | awk '$1 == "160000" {print $4}') if (( broken )); then warn "dead symlink scan found $broken issue(s) across $total dangling link(s) and $gitlink_count gitlink(s)" printf '%sSummary:%s recipe overlay=%s patch symlink=%s fork symlink=%s unclassified=%s submodule=%s\n' \ "$c_yellow" "$c_reset" "$stale_recipe_overlay" "$stale_patch_symlink" "$stale_fork_symlink" "$stale_unclassified" "$stale_submodule" return 1 fi ok "dead symlink scan clean ($total dangling links checked, $gitlink_count gitlinks checked)" } latest_prefix_mtime() { local latest=0 path ts for path in \ "$project_root/prefix/x86_64-unknown-redox/sysroot/x86_64-unknown-redox/lib/libc.a" \ "$project_root/prefix/x86_64-unknown-redox/relibc-install/x86_64-unknown-redox/lib/libc.a"; do if [[ -e "$path" ]]; then ts=$(stat -c %Y "$path") (( ts > latest )) && latest=$ts fi done printf '%s' "$latest" } fork_mtime() { local path="$1" git -C "$project_root" log -1 --format=%ct -- "$path" 2>/dev/null || printf '0' } components=(relibc kernel base) stale=0 prefix_ts="$(latest_prefix_mtime)" if (( simulate_staleness )); then prefix_ts=0 fi for component in "${components[@]}"; do path="local/sources/$component" fork_ts="$(fork_mtime "$path")" delta=$((fork_ts - prefix_ts)) if (( doctor )); then printf '%s: fork=%s prefix=%s delta=%s\n' "$path" "$fork_ts" "$prefix_ts" "$delta" fi if (( fork_ts > prefix_ts )); then printf '%s: lib too old by %s seconds\n' "$component" "$delta" stale=1 else ok "$component: prefix fresh" fi done if (( scan_dead_symlinks )); then if scan_dead_symlinks_mode; then exit 0 fi exit 1 fi if (( stale )); then warn "prefix is stale — run ./local/scripts/build-redbear.sh --upstream" exit 1 fi ok "prefix is fresh"