What:準則的環境變數表與命名總表加入 JSC_WIKI_REPO_CONTENTS 與目錄頁專用存取庫 一節,HASH 規則改為完整 40 碼。skill-check 的 Group 3 先讀上一輪決議,建議表加上 決議與決議日期兩欄,新增步驟 8 把稽核結果寫進 SKILLSET 頁。新增 check-page-name.sh 與兩份 SKILLSET 範本。 Why:優化建議原本每輪產出後就散掉,決議為延後的項目下一輪會重新掃、重新問一次, 正是 skill-check 自己第三個面向點名的毛病。SKILLSET_CONTENTS 是 14 個目錄頁裡 唯一沒有範本的,四支技能都被要求寫它,卻沒有欄位定義可套。 How:Group 1 補進三支現成但沒人呼叫的檢查腳本——ste100-lint.sh、check-wiki-rules.sh 與新增的 check-page-name.sh。讀不到上一輪決議時只停掉 Group 3,不再中止整輪:那兩組 完全不碰 wiki,金鑰失效就會鎖死整組技能唯一的稽核路徑。另外四支 meta 技能原本把目錄頁 寫進 SKILLSET 存取庫,一併改走 CONTENTS。
143 lines
7.1 KiB
Bash
Executable File
143 lines
7.1 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
# check-page-name.sh — 比對 wiki 頁名樣式三處是否一致。
|
|
#
|
|
# 用法: check-page-name.sh <root>
|
|
# <root> 是放 domain 存取庫的目錄,例如 /root/plugins。
|
|
# 目錄名同時吃 {domain} 與 jsc-{domain} 兩種寫法,也吃已安裝版面的版本目錄。
|
|
#
|
|
# 查哪三處:
|
|
# 1. {gitea}/tools/page-name.sh — 頁名樣式正本
|
|
# 2. {hooks}/hooks/comment-scope.sh — hook 內建的一份
|
|
# 3. {log}/tools/worklog-pending.sh — 工作日誌暫存內建的一份
|
|
#
|
|
# 為什麼三處各留一份,不共用函式: hook 必須自足。hook 在執行期去載別的 plugin 路徑,
|
|
# 那個 plugin 沒裝、版本不同、或路徑換了,hook 就當場失效,而且失效是安靜的。
|
|
# 共用函式換來的一致,付出的是 hook 的可用性。所以改成三處各自實作,一致性由稽核時比對。
|
|
#
|
|
# 每處斷言四項(判準見 jsc-meta references/guidelines.md 的「Wiki 頁命名總表」):
|
|
# 前兩處比對整個頁名,四項全查;第三處只驗純雜湊,沒有型別前綴,只查後兩項長度。
|
|
# 1. 型別清單 — 十五種型別逐一出現(只查比對整個頁名的那兩處): QUESTION、PLAN、ANALYZE、DELIVER、MAINTAIN、REPO、
|
|
# LOG、LEARN、ERROR、CHECK、REPORT、SKILLSET、TOOLING、MONITOR、CONTENTS。
|
|
# CONTENTS 是第十五種型別,「接受 CONTENTS」由這一項涵蓋。
|
|
# 2. 未知型別 — 出現 {某型別}_CONTENTS 或 {某型別}_{HASH} 的字樣,那個型別要在十五種之內。
|
|
# 3. 40 碼 — 接受完整 SHA-1 的 40 碼長度。
|
|
# 4. 8 碼 — 仍接受舊的 8 碼長度,遷移期間的舊頁名才讀得到。
|
|
# 5. H 開頭 — 仍接受 H 加 7 碼的舊頁名。這一項單獨列,因為三處很容易「一致地只收
|
|
# 純十六進位」——一致但都是錯的,前四項照樣全過。
|
|
#
|
|
# 判定方式與其極限: 本腳本做的是**文字層**比對,不執行那三支腳本。
|
|
# 三支的寫法各不相同(正規表示式、case 樣式、長度比較),沒有共同的可執行介面可以問,
|
|
# 要問就得各寫一套呼叫方式,那等於把三處的差異又抄第四份。
|
|
# 所以長度證據同時收樣式量詞({40}、{8,40})與檔頭文字(「40 碼」),兩者都算數。
|
|
# 代價講白: 這支抓得到「某一處漏了一種型別或一種長度」,抓不到「樣式寫法本身有錯」。
|
|
# 後者仍要人看,或由那三支自己的測試涵蓋。
|
|
#
|
|
# 輸出: 一行一個不合格項目,格式 {檔案}:{說明}(stderr);每處的判定摘要走 stdout。
|
|
# 結束碼: 0=三處一致,五項斷言全過
|
|
# 1=有不一致或有缺項,清單在 stderr(找不到其中一處或兩處也算這一碼)
|
|
# 2=用法錯誤(本腳本只吃一個參數)
|
|
# 3=三處一支都找不到——**什麼都沒查**,不等於通過。先確認 <root> 指對地方再重跑
|
|
set -u
|
|
|
|
usage() {
|
|
echo 'usage: check-page-name.sh <root>' >&2
|
|
exit 2
|
|
}
|
|
|
|
[ "$#" -eq 1 ] || usage
|
|
ROOT=${1%/}
|
|
[ -n "$ROOT" ] || usage
|
|
[ -d "$ROOT" ] || { echo "找不到根目錄:$ROOT" >&2; exit 3; }
|
|
|
|
# 十五種型別。這一行是本腳本的唯一真實來源,改動時同步 guidelines.md 的「Wiki 頁命名總表」。
|
|
TYPES='QUESTION PLAN ANALYZE DELIVER MAINTAIN REPO LOG LEARN ERROR CHECK REPORT SKILLSET TOOLING MONITOR CONTENTS'
|
|
|
|
# 長度證據的樣式。同時收樣式量詞與檔頭文字,理由見檔頭「判定方式與其極限」。
|
|
LEN40='\{40\}|\{8,40\}|\{40,40\}|40 碼|(-eq|=|\||\()[[:space:]]*40([^0-9]|$)'
|
|
LEN8='\{8\}|\{8,40\}|\{8,8\}|8 碼|(-eq|=|\||\()[[:space:]]*8([^0-9]|$)'
|
|
# H 開頭的舊頁名。舊演算法把首碼落在 0-9ABC 的改寫成 H 加原前 7 碼,十六個首碼有十三個
|
|
# 會命中,所以既有頁名多半長這樣。少了這一項,三處可以「都只收純十六進位」而一致地錯。
|
|
LENH='H\[0-9A-F\]\{7\}|H\[0-9A-Fa-f\]\{7\}|H 加(上)?(原)?前 7 碼|H\*'
|
|
|
|
hit=0
|
|
found=0
|
|
|
|
note() { # $1=檔案 $2=說明
|
|
printf '%s:%s\n' "$1" "$2" >&2
|
|
hit=1
|
|
}
|
|
|
|
find_file() { # $1=domain 目錄名(不含 jsc- 前綴) $2=存取庫內相對路徑
|
|
for _d in "$ROOT/$1" "$ROOT/jsc-$1"; do
|
|
[ -f "$_d/$2" ] && { printf '%s\n' "$_d/$2"; return 0; }
|
|
done
|
|
# 已安裝版面:一個 plugin 一個版本目錄,取排序最後的一份(通常即最新版)
|
|
_c=$(ls "$ROOT/jsc-$1"/*/"$2" "$ROOT/$1"/*/"$2" 2>/dev/null | sort | tail -n1)
|
|
[ -n "$_c" ] && [ -f "$_c" ] && { printf '%s\n' "$_c"; return 0; }
|
|
return 1
|
|
}
|
|
|
|
check_one() { # $1=檔案 $2=這一處的稱呼 $3=比對範圍:page=整個頁名 hash=只有雜湊
|
|
file=$1
|
|
label=$2
|
|
scope=$3
|
|
# 只有比對整個頁名的地方才該列型別。驗純雜湊的地方沒有型別前綴可比,
|
|
# 硬要它列十五種型別,等於逼它抄一份自己用不到的清單,下次改型別就多一處會漏。
|
|
[ "$scope" = 'page' ] || { check_len "$file"; printf '%s\t%s\n' "$label" "$file"; return 0; }
|
|
miss=''
|
|
for t in $TYPES; do
|
|
if ! grep -qE "(^|[^A-Za-z0-9_])$t([^A-Za-z0-9_]|\$)" "$file" 2>/dev/null; then
|
|
if [ -z "$miss" ]; then miss=$t; else miss="$miss、$t"; fi
|
|
fi
|
|
done
|
|
[ -z "$miss" ] || note "$file" "型別清單缺 $miss"
|
|
|
|
# 反向查:出現了十五種以外的型別,代表某一處還留著已經改名或已經刪掉的型別。
|
|
unknown=''
|
|
for u in $(grep -oE '(^|[^A-Za-z0-9_])[A-Z][A-Z0-9]{2,}_(CONTENTS|\{HASH\})' "$file" 2>/dev/null \
|
|
| sed -e 's/^[^A-Z]*//' -e 's/_.*$//' | sort -u); do
|
|
case " $TYPES " in
|
|
*" $u "*) ;;
|
|
*) if [ -z "$unknown" ]; then unknown=$u; else unknown="$unknown、$u"; fi ;;
|
|
esac
|
|
done
|
|
[ -z "$unknown" ] || note "$file" "出現十五種以外的型別 $unknown"
|
|
|
|
check_len "$file"
|
|
|
|
printf '%s\t%s\n' "$label" "$file"
|
|
}
|
|
|
|
check_len() { # $1=檔案。長度斷言三處都要過,驗純雜湊的那一處也不例外。
|
|
grep -qE "$LEN40" "$1" 2>/dev/null || note "$1" '沒有接受 40 碼長度的跡象,完整 SHA-1 的頁名會被判為不合法'
|
|
grep -qE "$LEN8" "$1" 2>/dev/null || note "$1" '沒有接受 8 碼長度的跡象,遷移期間的舊頁名會讀不到'
|
|
grep -qE "$LENH" "$1" 2>/dev/null || note "$1" '沒有接受 H 開頭舊頁名的跡象,八成的既有頁名會讀不到'
|
|
}
|
|
|
|
# 三處逐一查。找不到就記一行,不中止:一次把三處的狀況都報回去,比修一處重跑一次快。
|
|
scan() { # $1=domain 目錄名 $2=相對路徑 $3=稱呼 $4=比對範圍 page|hash
|
|
if f=$(find_file "$1" "$2"); then
|
|
found=$((found + 1))
|
|
check_one "$f" "$3" "$4"
|
|
else
|
|
printf '%s/%s:%s\n' "$1" "$2" "在 $ROOT 底下找不到這一處(也試過 jsc-$1 與版本目錄)" >&2
|
|
hit=1
|
|
fi
|
|
}
|
|
|
|
scan gitea tools/page-name.sh '正本' page
|
|
scan hooks hooks/comment-scope.sh 'hook' page
|
|
scan log tools/worklog-pending.sh '工作日誌暫存' hash
|
|
|
|
if [ "$found" -eq 0 ]; then
|
|
echo "三處一支都找不到,什麼都沒查:$ROOT" >&2
|
|
exit 3
|
|
fi
|
|
|
|
if [ "$hit" -eq 0 ]; then
|
|
echo "頁名樣式檢查通過:三處一致(型別十五種、40 碼、8 碼、H 加 7 碼)" >&2
|
|
else
|
|
echo "頁名樣式檢查有不一致:已查 $found 處,清單見 stderr" >&2
|
|
fi
|
|
exit $hit
|