What:把 sync-domains.sh 檔頭註解的簡體字「脏」改成正體「髒」;ste100-lint.sh 的 skip() 新增三個檔案:jsc-hooks 的 simplified.txt、ste100-guard.sh、lang-guard.sh。 Why:「脏」是既有的簡體字,擴充字表後才驗出來,正好證明檢查有效。另外三個檔案 裡的簡體字是被列舉、被討論的對象,不是被使用;掃它們會每次都命中卻永遠改不掉, 久了就會有人乾脆把整個檢查關掉。 How:skip() 沿用既有的 case 比對,同時吃絕對路徑與純檔名兩種寫法,並在註解裡 寫明為什麼要跳過,避免後人誤以為是漏掉。 Who:STE100 語言規則的機檢工具。
90 lines
4.0 KiB
Bash
Executable File
90 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env sh
|
||
# sync-domains.sh — 依 Gitea 正本 marketplace 把所有 domain 存取庫同步到本機。
|
||
#
|
||
# 用法: sync-domains.sh(不吃參數)
|
||
#
|
||
# 流程:
|
||
# 1. 透過 jsc-gitea/tools/gitea.sh 讀正本 marketplace
|
||
# (plugins/meta 的 .claude-plugin/marketplace.json),取得權威 domain 清單。
|
||
# 2. 本機缺少的 domain:用 gitea.sh clone-url plugins/{domain} 取網址後 clone。
|
||
# 3. 本機已有的 domain:git pull。工作區有未提交變更就跳過 pull,只在 stderr 提醒——
|
||
# 正在改的 repo 不該被自動 pull 覆蓋。
|
||
#
|
||
# 根目錄: 預設取本腳本位置的上兩層(meta/tools -> meta -> 根)。
|
||
# 用 JSC_PLUGINS_ROOT 覆寫,換機器不必改腳本。
|
||
# 存取庫目錄名: 先找 {root}/{domain},再找 {root}/jsc-{domain};都沒有才 clone 成 {root}/{domain}。
|
||
#
|
||
# 輸出: 一行一個 domain,格式 {domain}<TAB>{path}(stdout);警告與失敗說明走 stderr。
|
||
# 結束碼: 0=正本讀到、每個 domain 都在本機,而且每個既有存取庫都更新到最新
|
||
# 1=讀不到正本 marketplace 或找不到 gitea.sh(不輸出任何 domain)
|
||
# 2=正本讀到,但有 domain 沒能取得或 clone 失敗(已輸出其餘 domain)
|
||
# 3=每個 domain 都在本機,但有存取庫沒更新到最新:工作區髒而跳過 pull,
|
||
# 或 pull 失敗。stderr 會逐一列出這些路徑。**exit 0 才代表「全部最新」**;
|
||
# 拿 3 當乾淨會讓後續步驟改在落後的檔案上。
|
||
# 同時發生時回較嚴重的那個:2 蓋過 3。
|
||
# 環境變數: JSC_PLUGINS_ROOT(根目錄)
|
||
# JSC_SYNC_DRY_RUN=1(只印出會做什麼,不動檔案;不執行 pull/clone,
|
||
# 所以也不因為「沒更新」回 3)
|
||
set -u
|
||
|
||
HERE=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||
ROOT="${JSC_PLUGINS_ROOT:-$(CDPATH= cd -- "$HERE/../.." && pwd)}"
|
||
DRY="${JSC_SYNC_DRY_RUN:-}"
|
||
|
||
[ -d "$ROOT" ] || { echo "找不到 plugins 根目錄:$ROOT(可用 JSC_PLUGINS_ROOT 指定)" >&2; exit 1; }
|
||
|
||
GITEA=""
|
||
for g in "$ROOT/gitea/tools/gitea.sh" "$ROOT/jsc-gitea/tools/gitea.sh"; do
|
||
[ -f "$g" ] && { GITEA="$g"; break; }
|
||
done
|
||
[ -n "$GITEA" ] || { echo "找不到 gitea.sh:請先取得 jsc-gitea 存取庫" >&2; exit 1; }
|
||
|
||
mkt=$(sh "$GITEA" api GET /repos/plugins/meta/raw/.claude-plugin/marketplace.json 2>/dev/null) || mkt=""
|
||
[ -n "$mkt" ] || { echo "讀不到正本 marketplace:檢查 GITEA_HOST、GITEA_TOKEN 或 tea 登入" >&2; exit 1; }
|
||
|
||
DOMAINS=$(printf '%s\n' "$mkt" | sed -n 's/.*"name": *"jsc-\([a-z0-9-]*\)".*/\1/p' | sort -u)
|
||
[ -n "$DOMAINS" ] || { echo "正本 marketplace 裡沒有 jsc-{domain} 條目" >&2; exit 1; }
|
||
|
||
repo_path() { # $1=domain;印出既有路徑(return 0)或預設路徑(return 1)
|
||
for d in "$ROOT/$1" "$ROOT/jsc-$1"; do
|
||
[ -d "$d" ] && { printf '%s' "$d"; return 0; }
|
||
done
|
||
printf '%s' "$ROOT/$1"
|
||
return 1
|
||
}
|
||
|
||
rc=0
|
||
stale=0
|
||
for domain in $DOMAINS; do
|
||
if path=$(repo_path "$domain"); then
|
||
if [ -n "$(git -C "$path" status --porcelain 2>/dev/null)" ]; then
|
||
echo "工作區有未提交變更,跳過 pull,未更新到最新:$path" >&2
|
||
stale=1
|
||
elif [ "$DRY" = 1 ]; then
|
||
echo "[dry-run] git -C $path pull --ff-only" >&2
|
||
elif ! git -C "$path" pull --quiet --ff-only >/dev/null 2>&1; then
|
||
echo "pull 失敗,保留本機版本,未更新到最新:$path" >&2
|
||
stale=1
|
||
fi
|
||
else
|
||
url=$(sh "$GITEA" clone-url "plugins/$domain" 2>/dev/null) || url=""
|
||
if [ -z "$url" ]; then
|
||
echo "取不到 clone 網址,略過:plugins/$domain" >&2
|
||
rc=2
|
||
continue
|
||
fi
|
||
if [ "$DRY" = 1 ]; then
|
||
echo "[dry-run] git clone $url $path" >&2
|
||
elif ! git clone --quiet "$url" "$path" >/dev/null 2>&1; then
|
||
echo "clone 失敗:$url" >&2
|
||
rc=2
|
||
continue
|
||
fi
|
||
fi
|
||
printf '%s\t%s\n' "$domain" "$path"
|
||
done
|
||
|
||
# 2(取不到或 clone 失敗)比 3(沒更新到最新)嚴重,優先回報。
|
||
[ "$rc" -eq 0 ] && [ "$stale" -eq 1 ] && rc=3
|
||
exit $rc
|