feat: release 1.4.0 with isolated upgrades and device discovery
This commit is contained in:
1 parent
a6a3ee2eb0
commit
df66897ff4
41 files changed
+1564
-126
No files matched your search
@@ -13,7 +13,6 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import tomllib
|
||||
import urllib.request
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
@@ -42,34 +41,16 @@ def git(root: Path, *args: str, timeout: int = 15) -> str:
|
||||
return result.stdout.strip()
|
||||
|
||||
|
||||
def update_source(root: Path, port: int = 8000) -> int:
|
||||
"""Return 10 after a fast-forward (caller reloads launcher); never overwrite local work."""
|
||||
try:
|
||||
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
|
||||
with opener.open(f"http://127.0.0.1:{port}/api/status", timeout=2) as response:
|
||||
status = json.load(response)
|
||||
if (
|
||||
status.get("active_tasks")
|
||||
or status.get("queue")
|
||||
or (status.get("status") == "running" and status.get("pid"))
|
||||
):
|
||||
print(
|
||||
launch_text(
|
||||
"[WAIT] Tasks are active. Finish/stop them before updating dependencies or restarting.",
|
||||
"[等待] 有任务正在执行或排队。请先处理任务,再更新依赖或重启。",
|
||||
)
|
||||
)
|
||||
return 20
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
def update_source(root: Path, *, check_only: bool = False) -> int:
|
||||
"""Return 10 for an available/applied fast-forward, 1 on failure; preserve local work."""
|
||||
if not shutil.which("git"):
|
||||
print(
|
||||
launch_text(
|
||||
"[SKIP] Git is not installed. Continuing with local source; install Git for automatic source updates.",
|
||||
"[跳过] 未安装 Git,继续使用当前源码;安装 Git 后可自动检查更新。",
|
||||
"[ERROR] Install Git before upgrading; local source is preserved.",
|
||||
"[提示] 未安装 Git,无法升级;当前源码保持不变。",
|
||||
)
|
||||
)
|
||||
return 0
|
||||
return 1
|
||||
if not (root / ".git").exists():
|
||||
print(
|
||||
launch_text(
|
||||
@@ -77,8 +58,16 @@ def update_source(root: Path, port: int = 8000) -> int:
|
||||
"[跳过] 旧版源码包不含 Git 信息。请使用新版源码包或 Git 克隆;当前文件保持不变。",
|
||||
)
|
||||
)
|
||||
return 0
|
||||
return 1
|
||||
try:
|
||||
if not check_only and git(root, "status", "--porcelain"):
|
||||
print(
|
||||
launch_text(
|
||||
"[ERROR] Local changes exist; commit or back up first.",
|
||||
"[错误] 发现本地修改;请先提交或备份后再升级。",
|
||||
)
|
||||
)
|
||||
return 1
|
||||
branch = git(root, "symbolic-ref", "--quiet", "--short", "HEAD")
|
||||
remote = git(root, "config", "--get", f"branch.{branch}.remote")
|
||||
merge_ref = git(root, "config", "--get", f"branch.{branch}.merge")
|
||||
@@ -98,45 +87,53 @@ def update_source(root: Path, port: int = 8000) -> int:
|
||||
"[检查] 正在检查当前分支的远程更新...",
|
||||
)
|
||||
)
|
||||
git(root, "fetch", "--no-tags", remote, merge_ref, timeout=45)
|
||||
git(root, "fetch", "--no-tags", remote, merge_ref, timeout=5 if check_only else 45)
|
||||
target = git(root, "rev-parse", "FETCH_HEAD")
|
||||
current = git(root, "rev-parse", "HEAD")
|
||||
if current == target:
|
||||
print(launch_text("[OK] Source is up to date.", "[完成] 源码已是最新版。"))
|
||||
return 0
|
||||
if check_only:
|
||||
print(
|
||||
launch_text(
|
||||
"[UPDATE] A different upstream revision is available. Run update.bat (update-cn.bat for China mirrors).",
|
||||
"[更新] 远程版本有变化;请运行 update-cn.bat 或 update.bat 升级。",
|
||||
)
|
||||
)
|
||||
return 10
|
||||
if git(root, "status", "--porcelain"):
|
||||
print(
|
||||
launch_text(
|
||||
"[SKIP] Upstream differs, but local changes exist. Commit/back up your work before updating; continuing locally.",
|
||||
"[跳过] 发现本地修改;请先提交或备份。此次继续使用本地源码。",
|
||||
"[ERROR] Local changes appeared during the check. Upgrade stopped; files preserved.",
|
||||
"[错误] 检查期间出现本地修改;已停止升级,保留现有文件。",
|
||||
)
|
||||
)
|
||||
return 0
|
||||
return 1
|
||||
ancestor = git(root, "merge-base", "HEAD", target)
|
||||
if ancestor != current:
|
||||
print(
|
||||
launch_text(
|
||||
"[SKIP] Local branch is ahead or diverged. No automatic merge/rebase; continuing locally.",
|
||||
"[跳过] 本地分支领先或分叉,不自动合并;继续使用本地源码。",
|
||||
"[ERROR] Local branch is ahead or diverged. Upgrade stopped; no merge/rebase performed.",
|
||||
"[错误] 本地分支领先或分叉;已停止升级,不自动合并。",
|
||||
)
|
||||
)
|
||||
return 0
|
||||
return 1
|
||||
git(root, "merge", "--ff-only", target, timeout=30)
|
||||
print(
|
||||
launch_text(
|
||||
f"[UPDATED] Source {current[:12]} -> {target[:12]}. Reloading launcher and checking dependencies.",
|
||||
f"[已更新] 源码 {current[:12]} -> {target[:12]},重新载入启动脚本并检查依赖。",
|
||||
f"[UPDATED] Source {current[:12]} -> {target[:12]}. Preparing the updated installation.",
|
||||
f"[已更新] 源码 {current[:12]} -> {target[:12]},准备同步新版环境。",
|
||||
)
|
||||
)
|
||||
return 10
|
||||
except (RuntimeError, subprocess.TimeoutExpired) as exc:
|
||||
except (OSError, RuntimeError, subprocess.TimeoutExpired) as exc:
|
||||
print(
|
||||
launch_text(
|
||||
f"[WARN] {exc if isinstance(exc, RuntimeError) else 'Git update timed out.'} Continuing with local source.",
|
||||
"[提示] Git 更新失败或超时;请检查网络、凭据和仓库状态。继续使用当前源码。",
|
||||
f"[WARN] {exc if isinstance(exc, RuntimeError) else 'Git check failed or timed out.'} Local source is preserved.",
|
||||
"[提示] Git 检查/更新失败或超时;请检查网络、凭据和仓库状态。当前源码保持不变。",
|
||||
)
|
||||
)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
def _atomic_write(path: Path, text: str) -> None:
|
||||
@@ -406,12 +403,13 @@ def frontend_fingerprint(root: Path) -> str:
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("action", choices=["source", "mcp", "frontend-check", "frontend-mark"])
|
||||
parser.add_argument(
|
||||
"action", choices=["source", "source-check", "mcp", "frontend-check", "frontend-mark"]
|
||||
)
|
||||
parser.add_argument("--root", type=Path, default=ROOT)
|
||||
parser.add_argument("--port", type=int, default=8000)
|
||||
args = parser.parse_args()
|
||||
if args.action == "source":
|
||||
sys.exit(update_source(args.root, args.port))
|
||||
if args.action in {"source", "source-check"}:
|
||||
sys.exit(update_source(args.root, check_only=args.action == "source-check"))
|
||||
elif args.action == "mcp":
|
||||
sys.exit(refresh_mcp(args.root))
|
||||
else:
|
||||
|
||||
Reference in new issue
Block a user