"""Hub .env 读写(仅中控账号等少量键).""" from __future__ import annotations import re from pathlib import Path from typing import Dict, List _KEY_RE = re.compile(r"^([A-Za-z_][A-Za-z0-9_]*)=(.*)$") def _parse_line(line: str) -> tuple[str | None, str]: raw = line.rstrip("\n\r") if not raw.strip() or raw.lstrip().startswith("#"): return None, raw m = _KEY_RE.match(raw) if not m: return None, raw return m.group(1), raw def apply_env_updates(path: Path | str, updates: Dict[str, str]) -> List[str]: """更新或追加 .env 键;返回实际写入的 key 列表.不删其它行.""" env_path = Path(path) wanted = {str(k).strip(): str(v) for k, v in updates.items() if str(k).strip()} if not wanted: return [] lines: list[str] = [] if env_path.is_file(): lines = env_path.read_text(encoding="utf-8").splitlines(keepends=True) seen: set[str] = set() out: list[str] = [] changed: list[str] = [] for line in lines: key, _ = _parse_line(line) if key and key in wanted: out.append(f"{key}={wanted[key]}\n") seen.add(key) changed.append(key) else: if line.endswith("\n") or line.endswith("\r"): out.append(line if line.endswith("\n") else line + "\n") else: out.append(line + "\n") for key, val in wanted.items(): if key not in seen: out.append(f"{key}={val}\n") changed.append(key) env_path.parent.mkdir(parents=True, exist_ok=True) env_path.write_text("".join(out), encoding="utf-8") return changed