Files
ykxmz/_build/clean_ezhub_assets.py
T
xmz7891 2425f8694e 修发行版重复附件:重发前先删同名
Gitea 的发行版复用逻辑有 bug:发现标签已有发行版就复用,
但**没有先删同名附件**,于是每跑一次就多传一份。
调试期间同一个文件在 EzHub 上堆了 3 份(共 8 个附件,实际只要 3 个)。

修法:复用已有发行版时,先列出它的附件,
把和本次要传的同名的删掉,再传。

配套加了:
  * clean_ezhub_assets.py  清理已堆积的重复(同名只留最新,支持 --dry)
  * verify_releases.py     对账两个平台的发行版(标题/说明/附件/
                           管理页字眼/两边说明是否一致)

已清理:EzHub 从 8 个附件降到 3 个。
2026-10-07 12:36:35 +08:00

109 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
r'''清理 EzHub 发行版里重复的附件。
为什么会重复:
release_all.py 发现标签已有发行版时会"复用它",
但**没有先删同名附件**,于是每跑一次就多传一遍。
我调试时跑了几次,同一个文件就堆了 2~3 份。
这个脚本:同名附件只保留最新的一份,其余删掉。
(Gitea 的附件用 id 区分,创建时间看 created_at。)
'''
from __future__ import annotations
import json
import sys
import urllib.error
import urllib.request
from collections import defaultdict
from pathlib import Path
TOKEN = (Path.home() / ".ykxmz" / "ezhub_token").read_text(
encoding="utf-8").strip()
API = "https://git.261826.xyz/api/v1/repos/xmz/ykxmz"
TAG = "v1.8.0"
HEAD = {"Authorization": "token " + TOKEN, "User-Agent": "ykxmz-clean"}
def call(url: str, method: str = "GET"):
req = urllib.request.Request(url, method=method, headers=HEAD)
try:
with urllib.request.urlopen(req, timeout=60) as resp:
text = resp.read().decode("utf-8", "replace")
return resp.status, (json.loads(text) if text.strip() else {})
except urllib.error.HTTPError as exc:
body = exc.read().decode("utf-8", "replace")[:200]
return exc.code, body
def main() -> int:
dry = "--dry" in sys.argv
status, release = call("%s/releases/tags/%s" % (API, TAG))
if status != 200:
print(" [失败] 取发行版 HTTP %s: %s" % (status, release))
return 1
rid = release["id"]
assets = release.get("assets") or []
print(" 发行版 id=%s,附件 %d 个" % (rid, len(assets)))
# 按文件名分组
groups = defaultdict(list)
for a in assets:
groups[a.get("name") or "?"].append(a)
print()
print(" 分组情况:")
to_delete = []
for name, items in sorted(groups.items()):
# 新的排在前面(created_at 降序)
items.sort(key=lambda x: x.get("created_at") or "", reverse=True)
keep = items[0]
print(" %-32s 共 %d 份,保留 id=%s(%s)"
% (name, len(items), keep.get("id"),
(keep.get("created_at") or "")[:19]))
for extra in items[1:]:
print(" 删 id=%s(%s)" % (extra.get("id"),
(extra.get("created_at")
or "")[:19]))
to_delete.append(extra)
if not to_delete:
print()
print(" ✓ 没有重复,不用清理")
return 0
print()
if dry:
print(" 演练:会删 %d 个(去掉 --dry 真删)" % len(to_delete))
return 0
print(" 开始删除 %d 个重复附件…" % len(to_delete))
ok = 0
for asset in to_delete:
status, body = call("%s/releases/%s/assets/%s"
% (API, rid, asset.get("id")), method="DELETE")
if status in (200, 204):
print(" ✓ 删了 id=%s %s" % (asset.get("id"),
asset.get("name")))
ok += 1
else:
print(" ✗ id=%s HTTP %s %s" % (asset.get("id"), status, body))
print()
print(" 删除 %d/%d" % (ok, len(to_delete)))
# 复查
status, release = call("%s/releases/tags/%s" % (API, TAG))
assets = release.get("assets") or []
print()
print(" 现在剩 %d 个附件:" % len(assets))
for a in assets:
print(" %-32s %8.2f MB"
% (a.get("name"), (a.get("size") or 0) / 1024 / 1024))
return 0
if __name__ == "__main__":
sys.exit(main())