fix(mirror_sync): 修复大仓体积测量漏算松散对象 + 固化 tarball 路线

- PACK_KB 原先只取 size-pack,tarball 路线建的松散对象裸仓 size-pack=0
  → 误判体积=0、跳过 source-only 降级、错标 full(orca 因此被误标)。
  现合并 size-pack + size,松散对象也能正确触发 source-only。
- 新增 --tarball <url>:直接下载源码 tarball 绕过被封锁的 git 智能 HTTP 端点。
  本环境 github.com 经沙箱代理 502 封死 git clone,故 github 上游自动派生
  codeload URL 走 tarball(非 github 上游不受影响,仍走 git clone)。
- 回写档案时补 sync_note(之前 source-only 成功却留着 stale 的『暂未镜像』)。
This commit is contained in:
gitea-publish
2026-09-02 02:17:15 +08:00
parent 87dc8f78fa
commit f6f87ed004
+61 -3
View File
@@ -5,6 +5,9 @@
# bash scripts/mirror_sync.sh --id ipollowork
# bash scripts/mirror_sync.sh --id ipollowork --depth 200 # 超大仓只取近期历史
# bash scripts/mirror_sync.sh --id orca --blobless # 大仓懒拉 blob,只走源码快照
# bash scripts/mirror_sync.sh --id orca --tarball <url> # 直接下载 tarball 绕过 git 端点
# 说明:github.com 在本环境经沙箱代理 502 封死 git clone,脚本会自动把 github
# 上游改写为 codeload tarball 路线;非 github 上游不受影响。
#
# 可见性由档案的 business.license.redistributable 决定(L1/L2 → public,L3 → private)。
# 这条规则不能手工绕过:把 source-available 项目公开镜像,等于替对方做了一次
@@ -31,6 +34,10 @@ NO_FETCH="0"
# 大仓(尤其 blob 占比高)可把传输量从整包几百 MB 砍到几十 MB,且具备"克隆成功即落盘、
# 之后懒拉 blob 失败可重跑续传"的容错;代价是只能走源码快照(partial clone 不能按 mirror 推送)。
BLOBLESS="0"
# tarball 路线:直接下载上游源码 tarball(codeload.github.com 等),绕过被封锁的
# git 智能 HTTP 端点。本环境 github.com 经沙箱代理 502 封死,git clone 永不可用,
# 故 github 上游默认走 tarball(自动派生 codeload URL),得到的是无历史的源码快照。
TARBALL=""
while [[ $# -gt 0 ]]; do
case "$1" in
@@ -42,6 +49,7 @@ while [[ $# -gt 0 ]]; do
--set-public) SET_PUBLIC="1"; shift;;
--no-fetch) NO_FETCH="1"; shift;;
--blobless) BLOBLESS="1"; shift;;
--tarball) TARBALL="$2"; shift 2;;
*) echo "未知参数: $1" >&2; exit 1;;
esac
done
@@ -109,6 +117,14 @@ EXCLUDE_COUNT=${#EXCLUDE_PATHS[@]}
[[ -z "${UPSTREAM}" ]] && { echo "档案缺少 mirror.upstream" >&2; exit 1; }
# github.com 在本环境经沙箱代理 502 封死 git 智能 HTTP 端点,git clone 永远失败。
# 自动派生 codeload tarball URL(绕过 git 端点),github 上游默认走 tarball 路线。
# 非 github 上游(gitea/gitlab 等)不受影响,仍走正常 git clone。
if [[ -z "${TARBALL}" && "${UPSTREAM}" =~ ^https?://github\.com/([^/]+)/([^/]+?)(\.git)?/?$ ]]; then
TARBALL="https://codeload.github.com/${BASH_REMATCH[1]}/${BASH_REMATCH[2]}/tar.gz/refs/heads/main"
echo " 上游为 github.com(本环境 git 端点受限)→ 自动改用 tarball 路线: ${TARBALL}"
fi
echo "==> 镜像 ${ID}"
echo " 上游 : ${UPSTREAM}"
echo " 目标 : ${ORG}/${REPO_NAME}"
@@ -195,12 +211,51 @@ cleanup_broken() {
}
trap cleanup_broken EXIT
# 从 tarball 构建源码快照裸仓:下载 → 解包 → 剔除非源码素材 → 单提交 → 裸仓克隆。
# 适用于 git 端点不可达(本环境 github.com 被 502 封死)或仅需最新源码快照的场景。
build_from_tarball() {
echo " 从 tarball 构建源码快照(绕过 git 端点)..."
SOURCE_ONLY_FORCE="yes"
rm -rf "${MIRROR_DIR}"
local tmp
tmp="$(mktemp -d)"
local tarball="${tmp}/src.tar.gz"
local ok=0
for attempt in $(seq 1 8); do
if curl -sSL -C - -o "${tarball}" "${TARBALL}"; then
ok=1; break
fi
echo " ⚠ 第 ${attempt} 次下载失败,$(( attempt * 10 ))s 后重试 ..."
sleep $(( attempt * 10 ))
[[ ${attempt} -eq 8 ]] && { echo "tarball 下载八次均失败" >&2; exit 1; }
done
[[ ${ok} -eq 1 ]] || { echo "下载失败" >&2; exit 1; }
echo " 解包并剔除非源码素材 ..."
mkdir -p "${tmp}/src"
tar -xzf "${tarball}" -C "${tmp}/src" --strip-components=1
find "${tmp}/src" -type f \( \
-iname '*.png' -o -iname '*.gif' -o -iname '*.jpg' -o -iname '*.jpeg' \
-o -iname '*.webp' -o -iname '*.ico' -o -iname '*.mp4' -o -iname '*.mov' \
-o -iname '*.webm' -o -iname '*.wav' -o -iname '*.mp3' -o -iname '*.glb' \
-o -iname '*.ttf' -o -iname '*.woff' -o -iname '*.woff2' -o -iname '*.eot' \
-o -iname '*.pdf' -o -iname '*.zip' \) -delete
git -C "${tmp}/src" init -q
( cd "${tmp}/src" && git add -A \
&& git -c user.name='agent-radar' -c user.email='radar@local' \
commit -q -m "源码快照 @ $(date +%F) (tarball source-only)" )
git clone --bare "${tmp}/src" "${MIRROR_DIR}"
rm -rf "${tmp}"
echo " 已构建本地裸仓(源码快照,无历史)"
}
if [[ -d "${MIRROR_DIR}" ]] && ! repo_ok; then
echo " 清理上次中断的半成品裸仓 ..."
rm -rf "${MIRROR_DIR}"
fi
if [[ "${NO_FETCH}" == "1" ]]; then
if [[ -n "${TARBALL}" ]]; then
build_from_tarball
elif [[ "${NO_FETCH}" == "1" ]]; then
# 跳过上游更新,直接用本地裸仓生成快照。
# 2026-09-02 需要这个:本地裸仓已是完整的,只想重跑一次快照(改了排除项),
# 但 GitHub 恰好连不上("Empty reply from server"),脚本在 fetch 阶段就退出,
@@ -295,8 +350,10 @@ P_ENC="$(/Users/figmarlite/.workbuddy/binaries/python/envs/default/bin/python -c
# 所以推送前先量体积,超限则自动降级为「源码快照」:剔除图片/音视频/字体等
# 非源码素材——这些内容通常占一半以上体积,却不是"跟踪源码"要看的东西。
MAX_PUSH_MB="${MAX_PUSH_MB:-45}"
PACK_KB="$(git -C "${MIRROR_DIR}" count-objects -v | awk '/^size-pack:/{print $2}')"
PACK_MB=$(( PACK_KB / 1024 ))
# 既算打包对象(size-pack)也算松散对象(size):tarball 路线建的裸仓是松散对象,
# size-pack 为 0,不合并会误判体积=0、跳过 source-only 降级(orca 曾因此被错标 full)。
PACK_KB="$(git -C "${MIRROR_DIR}" count-objects -v | awk '/^size-pack:/{sp=$2} /^size:/{sz=$2} END{print sp+sz}')"
PACK_MB=$(( ${PACK_KB:-0} / 1024 ))
# blobless 镜像只能走源码快照:partial clone 不能按 mirror 推送。
[[ "${BLOBLESS}" == "1" ]] && SOURCE_ONLY_FORCE="yes"
MIRROR_MODE="full"
@@ -457,6 +514,7 @@ text = update_block(text, "mirror", {
"gitea_repo": f"{'gitinbox'}/{sys.argv[3]}",
"last_sync": today(),
"mode": sys.argv[4],
"sync_note": f"已于 {today()} 镜像({sys.argv[4]} 模式,由 mirror_sync.sh 自动回写)。",
})
p.write_text(text, encoding="utf-8")
PY