# -*- coding: utf-8 -*- r"""通用版本号升级(1.5.0 -> 1.6.0)。 只改**用户能看到版本号的地方**,不动那些当数据用的 "1.4.0/1.5.0": * HTTP User-Agent "LanRemote/1.4.0" —— 协议标识,不是产品版本, 而且 20 多个测试在断言它,动它要同步改一大片 * _tests 里当测试数据用的版本串 * _build 下的一次性脚本(历史记录) 改这些: android/AndroidManifest.xml versionCode / versionName android/build_apk.ps1 APK 文件名 + manifest 参数 _build/package_remote.py 三个产物名 windows/version_info.txt EXE 的文件版本 windows/lanremote/__init__.py __version__ docs/*.txt 三份文档 relay/relay.py VERSION _tests/test_package_remote.py 断言成品名 _tests/test_apk_contents.py 断言 APK 名 """ from __future__ import annotations import re import sys from pathlib import Path ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") OLD = sys.argv[1] if len(sys.argv) > 1 else "1.5.0" NEW = sys.argv[2] if len(sys.argv) > 2 else "1.6.0" OLD_CODE = str(int(OLD.split(".")[0]) * 100 + int(OLD.split(".")[1]) + 1) NEW_CODE = str(int(NEW.split(".")[0]) * 100 + int(NEW.split(".")[1]) + 1) def swap(path: Path, pairs, note: str) -> bool: if not path.is_file(): print(f" [跳过] {path.name} 不存在") return False raw = path.read_bytes() had_bom = raw.startswith(b"\xef\xbb\xbf") text = raw.decode("utf-8-sig") original = text for old, new in pairs: text = text.replace(old, new) if text == original: print(f" [跳过] {path.name}: 没有 {OLD}") return False path.write_bytes((b"\xef\xbb\xbf" if had_bom else b"") + text.replace("\r\n", "\n").encode("utf-8")) print(f" {path.name}: {note}") return True def main() -> int: print(f" 版本号 {OLD} -> {NEW}(versionCode {OLD_CODE} -> {NEW_CODE})") print() changed = 0 # ---- Android manifest ---- manifest = ROOT / "android" / "AndroidManifest.xml" if swap(manifest, [(f'android:versionCode="{OLD_CODE}"', f'android:versionCode="{NEW_CODE}"'), (f'android:versionName="{OLD}"', f'android:versionName="{NEW}"')], f"versionCode={NEW_CODE} versionName={NEW}"): changed += 1 # ---- APK 构建脚本 ---- apk_ps1 = ROOT / "android" / "build_apk.ps1" if swap(apk_ps1, [(f"ykxmz-watch-{OLD}.apk", f"ykxmz-watch-{NEW}.apk"), (f"--version-code {OLD_CODE}", f"--version-code {NEW_CODE}"), (f'--version-name "{OLD}"', f'--version-name "{NEW}"')], "APK 名 + 版本"): changed += 1 # ---- 打包脚本 ---- if swap(ROOT / "_build" / "package_remote.py", [(f'VERSION = "{OLD}"', f'VERSION = "{NEW}"')], f"VERSION={NEW}"): changed += 1 # ---- Windows EXE 版本信息 ---- if swap(ROOT / "windows" / "version_info.txt", [(f'"{OLD}.0"', f'"{NEW}.0"')], f"EXE 文件版本 {NEW}.0"): changed += 1 # ---- __init__ ---- if swap(ROOT / "windows" / "lanremote" / "__init__.py", [(f'"{OLD}"', f'"{NEW}"')], f"__version__={NEW}"): changed += 1 # ---- 中转 VERSION ---- if swap(ROOT / "relay" / "relay.py", [(f'VERSION = "{OLD}"', f'VERSION = "{NEW}"')], f"VERSION={NEW}"): changed += 1 # ---- 三份文档 ---- for path in sorted((ROOT / "docs").glob("*.txt")): raw = path.read_bytes() had_bom = raw.startswith(b"\xef\xbb\xbf") text = raw.decode("utf-8-sig") new_text = text.replace(OLD, NEW) if new_text != text: path.write_bytes((b"\xef\xbb\xbf" if had_bom else b"") + new_text.replace("\r\n", "\n").encode("utf-8")) print(f" docs/{path.name}") changed += 1 # ---- 会断言成品名的测试 ---- for name in ("test_package_remote.py", "test_apk_contents.py"): path = ROOT / "_tests" / name if not path.is_file(): continue text = path.read_text(encoding="utf-8") new_text = (text.replace(f"ykxmz-agent-{OLD}", f"ykxmz-agent-{NEW}") .replace(f"ykxmz-server-{OLD}", f"ykxmz-server-{NEW}") .replace(f"ykxmz-watch-{OLD}", f"ykxmz-watch-{NEW}")) if new_text != text: path.write_text(new_text, encoding="utf-8", newline="\n") print(f" _tests/{name}") changed += 1 print() print(f" 共改了 {changed} 处") print(f" 注意:HTTP UA 仍然是 LanRemote/1.4.0(协议标识,不是产品版本)") # 复核 print() print(" 复核:") checks = [ (manifest, f'versionName="{NEW}"'), (apk_ps1, f"ykxmz-watch-{NEW}.apk"), (ROOT / "_build" / "package_remote.py", f'VERSION = "{NEW}"'), ] for path, needle in checks: ok = needle in path.read_text(encoding="utf-8-sig") print(f" {path.name}: {'✓' if ok else '✗'} {needle}") return 0 if __name__ == "__main__": sys.exit(main())