fix(assistant): 判定是不是存取庫交給 git 自己回答

原本看 .git 在不在。這台機器的工作目錄底下剛好有一個目錄的 .git 只剩
一個空的 info/,git 一句「not a git repository」——而掃描把它算成一個
存取庫,還印成「沒有 origin」。那個說法讀起來像「這個存取庫還沒接遠端」,
不像「這裡根本不是存取庫」,兩件事的處置完全不同。

改成由 git 回答,並核對它認定的頂層就是那個目錄:只問「是不是在工作樹裡」
不夠,git 會從那裡往上找,.git 壞掉時它會找到上一層的存取庫然後答「是」。
兩邊都解成實體路徑再比,掃描起點帶符號連結那一段時字串才對得上。

多一個 not_a_repo= 判定行與收尾計數,執行那一支照樣原樣轉出。
存取庫數從 19 個變 18 個。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-07 10:39:43 +08:00
co-authored by Claude Opus 5
parent e53bb23f8e
commit 205da9b61f
7 changed files with 36 additions and 10 deletions
+30 -4
View File
@@ -16,6 +16,7 @@
# 結束碼:
# 0 掃到至少一個存取庫,而且每一個都對得出 REPO_{HASH}、路徑也都送得進殼
# 1 掃到了,但有幾個對不出頁名或路徑被拒。可用的那幾個照印,被拒的逐行印在 rejected=
# 有 .git 卻不被 git 認的那幾個也算在這一碼裡,印在 not_a_repo=
# 2 用法錯誤:不認得的子命令或選項、選項缺值、--scan-root 不是絕對路徑、--depth 超出範圍
# 3 掃描起點沒設定,或那條路徑不是存在的目錄——**什麼都沒掃**,不等於「這台機器沒有存取庫」
# 4 掃過了,一個 git 存取庫都沒有
@@ -183,7 +184,7 @@ sort -u -o "$CAND" "$CAND"
# --- 逐個判定 ---
N_REPO=0; N_REJ=0; N_UNNAMED=0; N_EXCL=0; N_LINK=0
N_REPO=0; N_REJ=0; N_UNNAMED=0; N_EXCL=0; N_LINK=0; N_FAKE=0
OUT="$TMPD/out.txt"
: >"$OUT"
@@ -195,9 +196,32 @@ while IFS= read -r d; do
emit "excluded=$d reason=在排除清單上"
continue
fi
# .git 可能是目錄(一般存取庫),也可能是檔案(worktree 與子模組)。兩種都算存取庫。
# .git 可能是目錄(一般存取庫),也可能是檔案(worktree 與子模組),所以先看它在不在,
# 但**在不在只是初篩,不是判定**。
[ -e "$d/.git" ] || continue
# 判定交給 git 自己。有 .git 不等於是存取庫:實測這台機器上有一個目錄底下的 .git 只剩
# 一個空的 info/,git 一句「not a git repository」,而只看 .git 在不在的掃描把它算成
# 一個存取庫、印成「沒有 origin」——那個說法讀起來像「這個存取庫還沒接遠端」,
# 不像「這裡根本不是存取庫」。兩件事的處置完全不同。
#
# 只問「是不是在工作樹裡」不夠:git 會從這個目錄往上找,$d/.git 壞掉時它會找到上一層的
# 存取庫然後回答「是」。所以要再核對它認定的頂層就是 $d 自己。兩邊都解成實體路徑再比,
# 掃描起點帶符號連結那一段時字串才對得上。
_top=$(git -C "$d" rev-parse --show-toplevel 2>/dev/null) || _top=''
_dreal=$(CDPATH= cd -P -- "$d" 2>/dev/null && pwd -P) || _dreal=''
_topreal=''
[ -n "$_top" ] && { _topreal=$(CDPATH= cd -P -- "$_top" 2>/dev/null && pwd -P) || _topreal=''; }
if [ -z "$_topreal" ] || [ "$_topreal" != "$_dreal" ]; then
N_FAKE=$((N_FAKE + 1))
if [ -z "$_top" ]; then
emit "not_a_repo=$d reason=有 .git 但 git 自己不認,多半是刪剩的殘骸"
else
emit "not_a_repo=$d reason=有 .git 但 git 認定的頂層是 $_top,這裡不是存取庫的根"
fi
continue
fi
case "$d" in
*[!A-Za-z0-9/._-]*)
N_REJ=$((N_REJ + 1))
@@ -255,7 +279,7 @@ else
done <"$OUT"
fi
emit "scan_root=$SCAN_ROOT depth=$DEPTH repos=$N_REPO unnamed=$N_UNNAMED rejected=$N_REJ excluded=$N_EXCL skipped_links=$N_LINK"
emit "scan_root=$SCAN_ROOT depth=$DEPTH repos=$N_REPO unnamed=$N_UNNAMED rejected=$N_REJ excluded=$N_EXCL skipped_links=$N_LINK not_a_repo=$N_FAKE"
case "$HASH_MODE" in
sha1sum|shasum) note '找不到共用那一支 hash-id(jsc-gitea 的 tools/hash-id),這一輪的頁名改用本機的 SHA-1 算。兩者是同一條規則、值相同,只是少了一層共用;--root 餵對就會用共用那一支。' ;;
@@ -267,7 +291,9 @@ esac
if [ "$N_REPO" -eq 0 ]; then
die 4 "掃過 $SCAN_ROOT 底下 $DEPTH 層,一個 git 存取庫都沒有。掃描起點指錯一層就會長這樣——工作目錄的版面是「一個存取庫一個子目錄」,指到某一個存取庫裡面就只剩它自己那一個,指到家目錄就一個都沒有。"
fi
if [ "$N_REJ" -gt 0 ] || [ "$N_UNNAMED" -gt 0 ]; then
[ "$N_FAKE" -gt 0 ] && warn "有 $N_FAKE 個目錄底下有 .git 卻不被 git 認,逐個印在上面的 not_a_repo= 那幾行。那不是「還沒接遠端的存取庫」,是刪剩的殘骸或者不是存取庫的根——只看 .git 在不在的掃描會把它算成一個存取庫。"
if [ "$N_REJ" -gt 0 ] || [ "$N_UNNAMED" -gt 0 ] || [ "$N_FAKE" -gt 0 ]; then
exit 1
fi
exit 0