From 7230fcb7f2577823d55e66d51bbe70b42789c677 Mon Sep 17 00:00:00 2001 From: Siddharth Balyan <52913345+alt-glitch@users.noreply.github.com> Date: Mon, 8 Jun 2026 20:29:41 +0530 Subject: [PATCH] revert(nix): drop the cp patchPhase workaround from #41867 (#42151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #41867 replaced mkNpmPassthru's patchPhase with `cp $npmDeps/package-lock.json package-lock.json`, on the theory that prefetch-npm-deps strips advisory fields (engines/os/cpu) from the cache lockfile. That diagnosis was wrong. prefetch-npm-deps copies the lockfile into the cache *verbatim* (prefetch-npm-deps/src/main.rs reads it and writes it unchanged). Building the cache fresh from the current root lockfile yields exactly the pinned npmDepsHash, and that cache's package-lock.json is byte-identical to the source (740 "engines" blocks on each side). With the hash correct, npmConfigHook's consistency check passes on its own — verified by building .#tui and .#default green with this (original) patchPhase. So the cp was unnecessary, and worse: it bypasses the consistency check wholesale, silently masking a genuinely stale npmDepsHash (a lockfile that changed without its hash being refreshed) instead of failing loudly. The original patchPhase keeps the check meaningful while still handling the one real cosmetic difference it was written for (trailing newlines); stale-hash drift is caught by the npmDepsHash itself plus the auto-fix workflow. Keeps the fix-lockfiles real-build verification and the nix-lockfile-fix.yml file-path fix from #41867 — only the patchPhase cp is reverted. --- nix/lib.nix | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/nix/lib.nix b/nix/lib.nix index 7c630ca9b8e..385fd84edf4 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -73,25 +73,24 @@ in patchPhase = '' runHook prePatch + # Normalize trailing newlines on the root lockfile so source and + # npm-deps always match, regardless of what fetchNpmDeps preserves. + sed -i -z 's/\\n*$/\\n/' package-lock.json - # prefetch-npm-deps stores a *normalized* package-lock.json in the deps - # cache: newer npm writes advisory fields (engines/os/cpu/funding/bin/…) - # into lockfile entries, and prefetch strips the ones that don't affect - # which tarballs are fetched. npmConfigHook then does a byte-for-byte - # diff of the source lockfile against the cache's copy and fails on - # those purely-cosmetic differences — this is what breaks cold builds - # on a nixpkgs whose prefetch-npm-deps strips fields the committed - # lockfile carries. - # - # Adopt the cache's own normalized lockfile as the source so the - # consistency check is trivially satisfied. The resolved dependency set - # (version/resolved/integrity/dependencies) is byte-identical either - # way — fetchNpmDeps derived the cache *from* this lockfile — so `npm - # ci` installs exactly the same tree; only advisory metadata is dropped. - # Genuine drift is still caught upstream: a changed lockfile that didn't - # get its npmDepsHash refreshed fails the fixed-output hash check before - # this phase ever runs. - cp --no-preserve=mode,ownership ${npmDeps}/package-lock.json package-lock.json + # Make npmConfigHook's byte-for-byte diff newline-agnostic by + # replacing its hardcoded /nix/store/.../diff with a wrapper that + # normalizes trailing newlines on both sides before comparing. + mkdir -p "$TMPDIR/bin" + cat > "$TMPDIR/bin/diff" << DIFFWRAP + #!/bin/sh + f1=\\$(mktemp) && sed -z 's/\\n*$/\\n/' "\\$1" > "\\$f1" + f2=\\$(mktemp) && sed -z 's/\\n*$/\\n/' "\\$2" > "\\$f2" + ${pkgs.diffutils}/bin/diff "\\$f1" "\\$f2" && rc=0 || rc=\\$? + rm -f "\\$f1" "\\$f2" + exit \\$rc + DIFFWRAP + chmod +x "$TMPDIR/bin/diff" + export PATH="$TMPDIR/bin:$PATH" runHook postPatch '';