mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 18:20:43 +00:00
EzHub 的 SSH 公钥在服务端一直被拒(Permission denied), 但令牌有 push 权限。所以发布脚本里 EzHub 改用 HTTPS + 令牌推,令牌只在进程内拼进 URL,不写进 .git/config。 顺带加了增量推送脚本 ezhub_push_all.py: 一次性推 44 个提交 = 117 MB,被 EzHub 的 nginx 413 拦了。 Git 推送是增量的,逐个提交推每包就小得多 —— 实测 44 个全部推成功。 脚本会先探测远端进度,只推缺的,并且对网络抖动自动重试。
114 lines
4.2 KiB
Python
114 lines
4.2 KiB
Python
# -*- coding: utf-8 -*-
|
||
r'''摸出 EzHub 的推送体积上限,并尝试增量推送。
|
||
|
||
背景:
|
||
一次性推 39 个提交 = 117 MB,EzHub 返回 413(nginx 的
|
||
client_max_body_size 拦了)。Gitee 上限大,所以一直没事。
|
||
|
||
思路:
|
||
第一个提交推成功后,后面每个提交只需要传"新增的对象"。
|
||
所以逐个提交推,每包就小得多。
|
||
但如果某个提交本身就加了个 35 MB 的二进制,那一包照样超限 ——
|
||
这里会把它找出来。
|
||
'''
|
||
from __future__ import annotations
|
||
|
||
import subprocess
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
|
||
GIT = r"C:\Program Files\Git\bin\git.exe"
|
||
TOKEN_FILE = Path.home() / ".ykxmz" / "ezhub_token"
|
||
|
||
OWNER, REPO, HOST = "xmz", "ykxmz", "git.261826.xyz"
|
||
|
||
|
||
def git(*args: str, timeout: int = 600) -> subprocess.CompletedProcess:
|
||
return subprocess.run([GIT] + list(args), cwd=str(ROOT),
|
||
capture_output=True, text=True,
|
||
encoding="utf-8", errors="replace",
|
||
timeout=timeout)
|
||
|
||
|
||
def main() -> int:
|
||
token = TOKEN_FILE.read_text(encoding="utf-8").strip()
|
||
url = "https://%s:%s@%s/%s/%s.git" % (OWNER, token, HOST, OWNER, REPO)
|
||
|
||
# 从旧到新的提交列表
|
||
out = git("rev-list", "--reverse", "HEAD").stdout or ""
|
||
commits = [c for c in out.splitlines() if c.strip()]
|
||
print(" 共 %d 个提交" % len(commits))
|
||
|
||
# 先看每个提交自身新增了多大的对象
|
||
print()
|
||
print(" 各提交新增的对象体积(找超大的):")
|
||
big = []
|
||
for index, sha in enumerate(commits, 1):
|
||
# 这个提交相对父提交新增的 blob
|
||
r = git("diff-tree", "-r", "--no-commit-id", "--objects",
|
||
"-r", sha)
|
||
entries = [ln for ln in (r.stdout or "").splitlines() if ln.strip()]
|
||
if not entries:
|
||
continue
|
||
payload = "\n".join(ln.split(" ", 1)[0] for ln in entries)
|
||
c = subprocess.run(
|
||
[GIT, "cat-file", "--batch-check=%(objecttype) %(objectsize) "
|
||
"%(objectname)"],
|
||
cwd=str(ROOT), input=payload, capture_output=True, text=True,
|
||
encoding="utf-8", errors="replace")
|
||
total = 0
|
||
for line in (c.stdout or "").splitlines():
|
||
parts = line.split()
|
||
if len(parts) >= 3 and parts[0] == "blob":
|
||
total += int(parts[1])
|
||
if total > 1024 * 1024:
|
||
msg = git("log", "-1", "--format=%s", sha).stdout.strip()[:50]
|
||
big.append((total, sha[:8], msg))
|
||
big.sort(reverse=True)
|
||
for total, sha, msg in big[:12]:
|
||
print(" %8.1f MB %s %s" % (total / 1024 / 1024, sha, msg))
|
||
if not big:
|
||
print(" (没有超过 1 MB 的)")
|
||
|
||
# 逐个推
|
||
print()
|
||
print(" 逐个提交推(每包只含新增对象):")
|
||
ok_until = 0
|
||
failed_at = None
|
||
for index, sha in enumerate(commits, 1):
|
||
r = subprocess.run(
|
||
[GIT, "push", url, "%s:refs/heads/main" % sha],
|
||
cwd=str(ROOT), capture_output=True, text=True,
|
||
encoding="utf-8", errors="replace", timeout=900)
|
||
err = (r.stderr or r.stdout or "").replace(token, "***")
|
||
if r.returncode == 0:
|
||
ok_until = index
|
||
if index % 5 == 0 or index == len(commits):
|
||
print(" 到第 %d/%d 个提交 ✓" % (index, len(commits)))
|
||
else:
|
||
tail = [ln for ln in err.strip().splitlines() if ln.strip()]
|
||
reason = tail[-1][:100] if tail else "?"
|
||
print(" 第 %d 个提交失败: %s" % (index, reason))
|
||
failed_at = (index, sha, reason)
|
||
break
|
||
|
||
print()
|
||
if failed_at is None:
|
||
print(" ✓ 全部推完(%d 个提交)" % len(commits))
|
||
return 0
|
||
|
||
index, sha, reason = failed_at
|
||
print(" 卡在第 %d 个提交 %s" % (index, sha))
|
||
print(" 原因: %s" % reason)
|
||
print()
|
||
print(" 这个提交新增的东西:")
|
||
r = git("show", "--stat", "--oneline", sha)
|
||
for line in (r.stdout or "").strip().splitlines()[:15]:
|
||
print(" " + line[:100])
|
||
return 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|