diff --git a/local/scripts/check-prefix-freshness.sh b/local/scripts/check-prefix-freshness.sh index b0c6b45da7..cfd66ced68 100755 --- a/local/scripts/check-prefix-freshness.sh +++ b/local/scripts/check-prefix-freshness.sh @@ -22,28 +22,93 @@ 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 \ @@ -85,6 +150,13 @@ for component in "${components[@]}"; do 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