cleanup() computed `isTmpPath` — the exact predicate for "is this path safe to delete" — and consulted it only inside the catch block, to classify a transient Windows error. The rmSync above it ran unconditionally against whatever path it was handed, with `recursive: true, force: true`. The guard existed and the destructive call never asked it. The chdir at the top of the function makes the failure mode worse rather than better: a wrong target first moves the process out of the tree, then deletes it. So the predicate moves above both, and an out-of-tmpdir path is refused before either can run. The refusal throws and names the path; returning quietly would reproduce the fail-open shape this wave exists to remove. The catch keeps its `&& isTmpPath` term. It is now always true, but it states the condition the swallow depends on rather than inheriting it from a check twenty lines up, and it stays correct if the guard is ever relaxed. All 300+ call sites resolve under os.tmpdir() today, including the two files that override TMPDIR — both create their override root through the real os.tmpdir() first — so nothing legitimate is refused. The regression test targets tests/ itself: a real directory that must never be deleted, so nothing is created and nothing needs tearing down. It asserts the throw names the path, that cwd is unchanged (the chdir hazard), and that a known file inside still exists — proving the directory was not emptied rather than merely still present. Whether tests/ is outside os.tmpdir() is environment-dependent: os.tmpdir() is /tmp on Linux, so a checkout under /tmp would put it inside, and there a correct guard would delete this directory rather than refuse it. The test asserts that precondition before calling cleanup, so that environment fails loudly instead of destructively. Refs #3057 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
28 KiB
28 KiB