fix(patch): keep the update marker on a no-op commit so a retry finalizes (#9567)
A conflicted `npm patch update` leaves an edit dir and a `.npm-patch-update.json` marker that the finalizing `npm patch commit` reads to finish the update — a metadata-only finalize that drops the renamed-from selector and tolerates the new version not being installed yet. `commit()` deleted that marker before checking whether the edit dir produced a diff. So a first commit that did no net work — the conflict resolved to the new version verbatim, giving "nothing to commit" — consumed the marker. A corrected retry then found none, ran a full reify, and failed `EPATCHUNUSED` (the rebased-to version isn't installed), leaving both the old and new selector in the manifest. The same loss happened on any non-finalizing path (e.g. the `EPATCHUNSAFE` throw). ## Fix The marker was deleted eagerly only to keep it out of the generated patch. Instead, keep it and teach `diffDirs` to skip it: - `diffDirs(originalDir, editedDir, ignore = new Set())` skips a set of root-relative filenames, like it already skips the root `package.json`. - `commit()` no longer deletes the marker — it reads/parses it (still throwing `EPATCHBADMARKER` on bad JSON before any diff), and passes `new Set([UPDATE_MARKER])` to `diffDirs`. The marker now survives any non-finalizing path, so a corrected retry still finalizes. A successful commit removes the whole edit dir (unless `--keep-edit-dir`), so nothing lingers. ## References Fixes #9566 Follow-up to #9439 (native dependency patching).
M
Manzoor Wani committed
5ddf6ccce5255d35da217d3e7342dde2bcb478d1
Parent: 1db885c
Committed by GitHub <noreply@github.com>
on 6/18/2026, 5:26:42 PM