mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 21:50:44 +00:00
139 lines
3.9 KiB
Python
139 lines
3.9 KiB
Python
# -*- coding: utf-8 -*-
|
||
r"""把整个项目打成压缩包,交给用户。
|
||
|
||
包含:全部源码(三端 + 安装包脚本 + 测试 + 构建脚本)+ 三份文档
|
||
+ 已构建好的成品(安装包 / APK / 两个 zip)
|
||
|
||
排除:
|
||
* .git 版本库(几十 MB,而且推上去过)
|
||
* dist_exe 40MB PyInstaller 产物,一条命令能重建
|
||
* _build/pyinstaller_work 同上
|
||
* __pycache__ / *.pyc
|
||
* _tests/out_* / _tests/received 测试临时数据
|
||
* _build/jc* 编译中间产物
|
||
* **_build/.gitee_token** ← Gitee 令牌,**绝对不能进包**
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import re
|
||
import sys
|
||
import zipfile
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
|
||
OUT = ROOT / "dist" / "ykxmz-项目完整源码.zip"
|
||
|
||
# 目录级排除(按相对路径前缀)
|
||
EXCLUDE_DIRS = (
|
||
".git",
|
||
"dist_exe",
|
||
"_build/pyinstaller_work",
|
||
"_build/jc_all",
|
||
"_build/jc_tls",
|
||
"_build/jc_tls2",
|
||
"_build/jc_v15",
|
||
"_build/out_java",
|
||
"_build/out_app",
|
||
"_tests/out_java",
|
||
"_tests/out_app",
|
||
"_tests/received",
|
||
"_tests/_stubdata",
|
||
"_tests/shots",
|
||
"__pycache__",
|
||
"android/build",
|
||
"android/gen",
|
||
"android/bin",
|
||
"windows/data",
|
||
)
|
||
|
||
# 文件名级排除
|
||
EXCLUDE_NAMES = {
|
||
".gitee_token",
|
||
"Thumbs.db",
|
||
"desktop.ini",
|
||
".DS_Store",
|
||
}
|
||
|
||
# 后缀级排除
|
||
EXCLUDE_SUFFIXES = (
|
||
".pyc", ".pyo", ".pyd",
|
||
".log", ".tmp", ".toc", ".pyz", ".pkg",
|
||
".bak", ".orig",
|
||
)
|
||
|
||
# 要打进去的顶层条目(只打这些,别的一律不要)
|
||
INCLUDE_TOP = (
|
||
"windows", "android", "relay", "installer", "docs", "tools",
|
||
"_tests", "_build",
|
||
"README.md", "LICENSE.md", ".gitignore",
|
||
"diag", "dist",
|
||
)
|
||
|
||
# dist 里只带上成品,别把中间目录带进去
|
||
DIST_KEEP = (".exe", ".apk", ".zip", ".idsig", ".txt")
|
||
|
||
|
||
def excluded(rel: str, path: Path) -> bool:
|
||
rel_posix = rel.replace("\\", "/")
|
||
for prefix in EXCLUDE_DIRS:
|
||
if rel_posix == prefix or rel_posix.startswith(prefix + "/"):
|
||
return True
|
||
if path.name in EXCLUDE_NAMES:
|
||
return True
|
||
if path.suffix.lower() in EXCLUDE_SUFFIXES:
|
||
return True
|
||
# dist 目录只留成品
|
||
if rel_posix.startswith("dist/"):
|
||
if path.is_file() and not path.name.lower().endswith(DIST_KEEP):
|
||
return True
|
||
if rel_posix == "dist" and path.is_dir():
|
||
return False
|
||
return False
|
||
|
||
|
||
def main() -> int:
|
||
if OUT.exists():
|
||
OUT.unlink()
|
||
OUT.parent.mkdir(parents=True, exist_ok=True)
|
||
|
||
count = 0
|
||
total = 0
|
||
skipped_token = False
|
||
|
||
with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED,
|
||
compresslevel=6) as archive:
|
||
for top in INCLUDE_TOP:
|
||
root = ROOT / top
|
||
if not root.exists():
|
||
print(f" [跳过] 没有 {top}")
|
||
continue
|
||
|
||
if root.is_file():
|
||
archive.write(root, f"ykxmz/{top}")
|
||
count += 1
|
||
total += root.stat().st_size
|
||
continue
|
||
|
||
for path in sorted(root.rglob("*")):
|
||
rel = str(path.relative_to(ROOT))
|
||
if excluded(rel, path):
|
||
if path.name == ".gitee_token":
|
||
skipped_token = True
|
||
continue
|
||
if path.is_dir():
|
||
continue
|
||
archive.write(path, f"ykxmz/{rel.replace(chr(92), '/')}")
|
||
count += 1
|
||
total += path.stat().st_size
|
||
|
||
size = OUT.stat().st_size / 1024 / 1024
|
||
print(f" ✓ {OUT.name}")
|
||
print(f" {count} 个文件,原始 {total / 1024 / 1024:.1f} MB,"
|
||
f"压缩后 {size:.1f} MB")
|
||
print(f" Gitee 令牌已排除: {skipped_token or '(本来就没扫到)'}")
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|