diff --git a/updater.py b/updater.py index 72c7338..b69d02c 100644 --- a/updater.py +++ b/updater.py @@ -1,17 +1,35 @@ -"""Git 热更新:定期检查远端新版本,更新前先推送通知,再拉取并重启进程。 +"""Git 热更新:定期检查远端新版本,更新前先推送通知,再拉取、同步依赖并重启进程。 -基于 GitPython。 +基于 GitPython。重启前会执行 `uv sync` 使依赖与新版本一致,失败则不重启。 """ import asyncio import logging import os +import shutil +import subprocess import sys +from pathlib import Path import git log = logging.getLogger("updater") +def _find_uv() -> str | None: + for name in ("uv", "uv.exe"): + path = shutil.which(name) + if path: + return path + # 常见安装位置兜底 + for path in ( + Path.home() / ".local" / "bin" / "uv", + Path.home() / ".cargo" / "bin" / "uv.exe", + ): + if path.exists(): + return str(path) + return None + + class Updater: def __init__(self, ob, cfg: dict): self.ob = ob @@ -62,6 +80,23 @@ class Updater: "[更新] 检测到新版本,正在更新并重启机器人...", self.groups, self.friends) await asyncio.to_thread(self.repo.remotes.origin.pull, "--ff-only") + + # 同步依赖(pyproject/uv.lock 可能在新版本中有变化) + uv = _find_uv() + if uv is None: + log.warning("未找到 uv,跳过依赖同步,直接重启") + else: + log.info("执行 uv sync 同步依赖...") + r = await asyncio.to_thread( + subprocess.run, + [uv, "sync"], capture_output=True, text=True, + encoding="utf-8", errors="replace", timeout=300, + ) + if r.returncode != 0: + log.error("uv sync 失败,取消重启: %s", (r.stderr or "")[-500:]) + return + log.info("依赖同步完成") + log.warning("更新完成,重启进程...") await asyncio.sleep(1) os.execv(sys.executable, [sys.executable] + sys.argv)