From a997c04cdac0fa73cb8755709bb5fd0f544a7c61 Mon Sep 17 00:00:00 2001 From: JOJO <1498581755@qq.com> Date: Thu, 10 Sep 2026 18:38:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(utils):=20atomic=5Fwrite=5Fjson=20=E7=A9=BF?= =?UTF-8?q?=E9=80=8F=E7=AC=A6=E5=8F=B7=E9=93=BE=E6=8E=A5=EF=BC=8C=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E8=AE=BE=E7=BD=AE=E4=BF=9D=E5=AD=98=E5=90=8E=E5=9B=9E?= =?UTF-8?q?=E9=80=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit os.replace 目标是符号链接时会替换链接本身,产生与共享文件脱钩的普通文件 (分叉)。docker/web 模式工作区的 personalization.json 是指向用户级共享 文件的符号链接,保存后分叉被 user_manager 的链接校准丢弃,导致个人空间 设置(如 external_session_header)保存成功却立刻回退。修复为写入前先 resolve 符号链接到真实文件再原子替换;普通文件路径行为不变。 --- utils/atomic_io.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/utils/atomic_io.py b/utils/atomic_io.py index 751c3e78..4427ebc2 100644 --- a/utils/atomic_io.py +++ b/utils/atomic_io.py @@ -59,8 +59,18 @@ def atomic_write_json(path: PathLike, data: Dict[str, Any]) -> None: 防止写中断留下半截文件(直接 open(path,"w") 覆写的风险)。 临时文件与目标同目录,保证 os.replace 同卷原子性;异常时清理临时文件。 + + 符号链接写穿(2026-09-10 修复):目标是符号链接时必须先解析到真实文件再 + 原子替换。否则 os.replace 会把链接本身替换成普通文件(分叉),真实文件 + 根本没被写入——个人空间 personalization.json 共享链接曾因此被 + user_manager 的链接校准判为分叉并丢弃,表现为「设置保存后立刻回退」。 """ target = Path(path) + try: + if target.is_symlink(): + target = target.resolve() + except Exception: + pass target.parent.mkdir(parents=True, exist_ok=True) fd, tmp_name = tempfile.mkstemp( prefix=f".{target.name}.", suffix=".tmp", dir=str(target.parent)