2.1 KiB
Agent Note: 用 unlink 删除过期的 profile 回退链接而非 rmSync
Status: implemented
English | 中文
问题
healProfilesModuleFallback 在安装位置迁移时会把 $DSH_HOME/profiles/node_modules 中的条目重新指向新目标,而 Windows 主机上这些条目是 junction。ensureSymlink 原先用 rmSync(link) 删除过期条目,但 Node 在删除时把 junction 当作目录处理:不带 recursive 的 rmSync 会抛 ERR_FS_EISDIR,于是从迁移后的安装或第二个 worktree 启动时,每次都会在应用引导前崩溃。replaces a wrong symlink 单元测试在 Windows 上正好在该删除调用处复现了这一崩溃。
决策
ensureSymlink 改用 unlinkSync(link) 删除过期链接。unlink 在所有平台上都只删除重解析点或符号链接本身、绝不进入目标目录,从而保住该函数“真实目录永远不会被删除”的大声失败保证。profile-plugin-bundles 决策继续拥有回退目录的双锚点解析;本 note 只拥有“用哪个删除原语”这一决定。
考虑过的替代方案
rmSync(link, { recursive: true })。 Node 24 上它只删 junction、不跟随目标,但 recursive 会在 lstat 守卫与删除之间链接被替换成真实目录时静默删除该目录,削弱守卫存在所依据的大声失败契约。
rmdirSync(link)。 Windows 上同样能删 junction,但它读起来像“删目录”,而 unlinkSync 才是仓库现有的 junction 清理惯例。
无条件删除并重建所有条目。 正确,但每次启动都翻动未变化的链接,并扩大并发修复的竞态窗口。
后果
Windows 启动现在可以修复迁移后的安装或第二个 checkout,而不是以 ERR_FS_EISDIR 崩溃;POSIX 行为不变,因为 unlinkSync 同样能 unlink 普通符号链接。现有的 replaces a wrong symlink 测试在 Windows 上从复现崩溃变为通过。两个并发 healer 删除同一过期链接时,第二次删除仍会以 ENOENT 浮现,与原先的 rmSync 实现一致。