# -*- 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())