修好「總管可以放行」那道門——它在 Linux(=每個雲端 session)上是焊死的(inkstone/ISEP#90 ④)
三支閘(prod-write-guard/main-and-prod-push-guard/stage-before-prod-guard)
判斷戳記新不新,都寫成這一行:
MT=$(stat -f %m "$STAMP" 2>/dev/null || stat -c %Y "$STAMP" 2>/dev/null || echo 0)
macOS(BSD stat)上 `-f %m` 就是 mtime,對的。
**GNU coreutils 的 `-f` 是「顯示檔案系統資訊」**,而且它一邊回非零、
一邊往 stdout 吐一整段區塊 ⇒ `||` 接上的秒數被那段文字污染
⇒ 下一行的 `case "$NOW$MT" in *[!0-9]*) return 1` 必然命中
⇒ **在 Linux 上那三支閘的戳記永遠不會被接受。**
後果不是少一個便利功能:那三支閘都是「擋下來、但總管看過就能放行」,
而放行那道門在雲端打不開 ⇒ **它們在雲端等於純擋**,
總管照著閘自己印的指示做,做幾次都打不開,閘也不會告訴他門是壞的
(inkstone/InkStoneCo#99 那次「連續四次蓋不出戳記」就是這個形狀)。
· hooks/lib/mtime.sh:先 `-c %Y`(GNU)再 `-f %m`(BSD),**每一步都驗是不是純數字**
——這個 bug 的成因正是「命令失敗了卻還是印了東西」,只看離開碼會再被騙一次。
四支用到的檔各自帶一份 inline fallback:這道門不能因為少一個檔案就再關上一次。
· scripts/gate-ok:把散在各閘訊息裡的七種逃生口收斂成一個名字、一種形狀
(`gate-ok <閘名> [參數]`)。原因是逃生口原本是「臨時湊出來的 Bash 指令」,
而臨時湊的指令沒有穩定形狀可以事先放行——settings.json 的 allow 只能逐條完全比對,
多一個 `&&`、換一個 session id 就落在規則外。它蓋的戳記與閘原本認的完全同一個檔、
同一種語意(單次、綁 repo、綁 session、有效期都沒動),換掉的只有「怎麼蓋」。
測試 hooks/tests/gate-ok.test.sh:16/16。既有的三支測試(29/16/10)不受影響。
拿 main 跑同一份:②⑤(門打得開)紅、⑥⑦⑧(門沒變寬)全綠
⇒ 這支補的正是既有測試從來沒驗過的那半邊。
This commit is contained in:
@@ -57,6 +57,18 @@ except Exception: print(False)
|
||||
# **2 一律不報。** 誤攔比漏擋更該修(leo 2026-08-17:文字層那些閘 8 次誤攔、
|
||||
# 0 次正確攔截)——把「離線」當成「你沒推」,就是拿雜訊懲罰謹慎。
|
||||
|
||||
# 🔴 戳記的 mtime 一律走 lib/mtime.sh:舊寫法(`stat -f %m || stat -c %Y`)在 Linux 上
|
||||
# **永遠算不出數字**(GNU 的 `-f` 是「檔案系統資訊」,它一邊回非零一邊吐一整段文字,
|
||||
# 於是後面接上的秒數被那段垃圾污染)⇒ 這支閘給總管的逃生口在雲端整個焊死,
|
||||
# 而閘不會告訴他門是壞的(inkstone/ISEP#90 ④,全文見 hooks/lib/mtime.sh)。
|
||||
# lib 不在時就地補一份同順序的定義——這道門不能因為少一個檔案就再關上一次。
|
||||
. "$(dirname "$0")/lib/mtime.sh" 2>/dev/null || file_mtime() {
|
||||
_fm=$(stat -c %Y "$1" 2>/dev/null || true)
|
||||
case "${_fm:-}" in ''|*[!0-9]*) _fm=$(stat -f %m "$1" 2>/dev/null || true) ;; esac
|
||||
case "${_fm:-}" in ''|*[!0-9]*) _fm=0 ;; esac
|
||||
printf '%s' "$_fm"
|
||||
}
|
||||
|
||||
GIT_ASK="env GIT_TERMINAL_PROMPT=0 GIT_ASKPASS=/bin/echo GIT_SSH_COMMAND=ssh\ -oBatchMode=yes"
|
||||
_TO=""
|
||||
command -v timeout >/dev/null 2>&1 && _TO="timeout 15"
|
||||
@@ -72,7 +84,7 @@ ls_remote_heads() {
|
||||
_lr_cache="${UNPUSHED_CACHE_DIR:-/tmp}/.unpushed-lsremote-$_lr_key"
|
||||
if [ -f "$_lr_cache" ]; then
|
||||
_lr_now=$(date +%s 2>/dev/null || echo 0)
|
||||
_lr_mt=$(stat -f %m "$_lr_cache" 2>/dev/null || stat -c %Y "$_lr_cache" 2>/dev/null || echo 0)
|
||||
_lr_mt=$(file_mtime "$_lr_cache")
|
||||
case "$_lr_now$_lr_mt" in *[!0-9]*) _lr_mt=0 ;; esac
|
||||
if [ "$_lr_mt" -gt 0 ] && [ $((_lr_now - _lr_mt)) -lt 120 ]; then
|
||||
[ -s "$_lr_cache" ] || return 1
|
||||
|
||||
Reference in New Issue
Block a user