#!/bin/bash # check-legacy-paths.sh — 相容閘:已發佈的安裝/更新腳本會抓的每個遠端路徑,都必須還在 # # 這支存在的理由(SDD jdd-dual-profile 發現⑦ + 決策 D3): # install.sh / update.sh 是**逐檔 curl**:檔案清單與遠端路徑**寫死在腳本裡**。 # 而 update.sh 的「自我更新」在腳本**尾端**——舊實例這一輪跑的是**舊腳本**。 # ⇒ 只要框架把某個既有檔搬走/改名,舊實例的那一輪就是**整排 404**, # 而且它們不會自動好:更新機制本身壞了,就沒有下一次更新來修它。 # # 前科:1.16.0「update/install 來源改指 Gitea」——來源一改, # 舊實例的自動更新當場死掉(CHANGELOG 1.16.0 有記)。同一種病。 # # 所以鐵律是:**遠端路徑對既有實例是契約,只增不移。** # 要搬版面 → 先在原路徑留相容檔(轉址說明/原內容),確認本閘綠了才准動。 # # 作法: # 從「已發佈版本」的 install.sh / update.sh 裡抽出所有 $REPO_URL/... $TEMPLATE_URL/... # $SCRIPTS_URL/... 引用,映射回本 repo 的實體路徑,逐一確認檔案存在。 # # 誠實限制: # · 只驗「路徑還在不在」,不驗內容還對不對(舊腳本抓到新內容仍可能語意不相容)。 # · 基準是 git 裡的已發佈版本(預設 HEAD);再更老的版本若引用過更多路徑, # 本閘看不到——要驗更早的版本,用 BASE= 指定。 # # 用法: # bash scripts/check-legacy-paths.sh # 以 HEAD 為已發佈基準 # BASE=dc4fe67 bash scripts/check-legacy-paths.sh set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$REPO_ROOT" BASE="${BASE:-HEAD}" # ── 取出基準版本的兩支腳本 ──────────────────────────── TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT for s in install.sh update.sh; do if ! git show "$BASE:scripts/$s" > "$TMP/$s" 2>/dev/null; then echo "⚠️ 基準 $BASE 沒有 scripts/$s,略過" >&2 : > "$TMP/$s" fi done # ── 抽出遠端引用 → 映射成本地實體路徑 ────────────────── # $REPO_URL/x → template/x # $TEMPLATE_URL/x → template/x # $SCRIPTS_URL/x → scripts/x extract_paths() { grep -oE '\$\{?(REPO_URL|TEMPLATE_URL|SCRIPTS_URL)\}?/[A-Za-z0-9._/-]+' "$1" 2>/dev/null \ | sed -e 's|\${*REPO_URL}*/|template/|' \ -e 's|\${*TEMPLATE_URL}*/|template/|' \ -e 's|\${*SCRIPTS_URL}*/|scripts/|' \ || true } ALL="$( { extract_paths "$TMP/install.sh"; extract_paths "$TMP/update.sh"; } | sort -u )" if [ -z "$ALL" ]; then echo "⚠️ 在 $BASE 的腳本裡找不到任何遠端引用——抽取規則可能過時,本閘等同關閉" >&2 exit 1 fi TOTAL=0 MISSING=0 MISSING_LIST="" while IFS= read -r p; do [ -z "$p" ] && continue TOTAL=$((TOTAL + 1)) if [ ! -e "$p" ]; then MISSING=$((MISSING + 1)) MISSING_LIST="${MISSING_LIST} ✗ ${p}"$'\n' fi done <<< "$ALL" if [ "$MISSING" -gt 0 ]; then cat >&2 <