From 1f37f0809175e1df77cc3103cf851ec80a31fffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gutyina=20Gerg=C5=91?= Date: Fri, 12 Dec 2025 11:38:37 +0100 Subject: [PATCH] pnpm.fetchDeps: output a tarball from fetcherVersion 3 --- .../javascript.section.md | 3 +- .../tools/pnpm/fetch-deps/default.nix | 31 +++++++++++++++++-- .../tools/pnpm/fetch-deps/pnpm-config-hook.sh | 12 ++++--- .../tools/pnpm/fetch-deps/serve.nix | 11 ++++++- 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/doc/languages-frameworks/javascript.section.md b/doc/languages-frameworks/javascript.section.md index 508b8f3f97f6..f85a416fee86 100644 --- a/doc/languages-frameworks/javascript.section.md +++ b/doc/languages-frameworks/javascript.section.md @@ -354,7 +354,7 @@ stdenv.mkDerivation (finalAttrs: { pnpmDeps = pnpm.fetchDeps { inherit (finalAttrs) pname version src; - fetcherVersion = 2; + fetcherVersion = 3; hash = "..."; }; }) @@ -501,6 +501,7 @@ Changes can include workarounds or bug fixes to existing PNPM issues. - 1: Initial version, nothing special - 2: [Ensure consistent permissions](https://github.com/NixOS/nixpkgs/pull/422975) +- 3: [Build a reproducible tarball](https://github.com/NixOS/nixpkgs/pull/469950) ### Yarn {#javascript-yarn} diff --git a/pkgs/development/tools/pnpm/fetch-deps/default.nix b/pkgs/development/tools/pnpm/fetch-deps/default.nix index 01a4e7be4a4d..4fb7c6d6d736 100644 --- a/pkgs/development/tools/pnpm/fetch-deps/default.nix +++ b/pkgs/development/tools/pnpm/fetch-deps/default.nix @@ -8,6 +8,7 @@ makeSetupHook, pnpm, yq, + zstd, }: let @@ -16,6 +17,7 @@ let supportedFetcherVersions = [ 1 # First version. Here to preserve backwards compatibility 2 # Ensure consistent permissions. See https://github.com/NixOS/nixpkgs/pull/422975 + 3 # Build a reproducible tarball. See https://github.com/NixOS/nixpkgs/pull/469950 ]; in { @@ -72,6 +74,7 @@ in moreutils args.pnpm or pnpm' yq + zstd ]; impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [ "NIX_NPM_REGISTRY" ]; @@ -87,7 +90,15 @@ in export HOME=$(mktemp -d) - storePath=$out + # For fetcherVersion < 3, the pnpm store files are placed directly into $out. + # For fetcherVersion >= 3, it is bundled into a compressed tarball within $out, + # without distributing the uncompressed store files. + if [[ ${toString fetcherVersion} -ge 3 ]]; then + mkdir $out + storePath=$(mktemp -d) + else + storePath=$out + fi # If the packageManager field in package.json is set to a different pnpm version than what is in nixpkgs, # any pnpm command would fail in that directory, the following disables this @@ -146,6 +157,19 @@ in find $storePath -type d -print0 | xargs -0 chmod 555 fi + if [[ ${toString fetcherVersion} -ge 3 ]]; then + ( + cd $storePath + + # Build a reproducible tarball, per instructions at https://reproducible-builds.org/docs/archives/ + tar --sort=name \ + --mtime="@$SOURCE_DATE_EPOCH" \ + --owner=0 --group=0 --numeric-owner \ + --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime \ + --zstd -cf $out/pnpm-store.tar.zst . + ) + fi + runHook postFixup ''; @@ -168,7 +192,10 @@ in configHook = makeSetupHook { name = "pnpm-config-hook"; - propagatedBuildInputs = [ pnpm ]; + propagatedBuildInputs = [ + pnpm + zstd + ]; substitutions = { npmArch = stdenvNoCC.targetPlatform.node.arch; npmPlatform = stdenvNoCC.targetPlatform.node.platform; diff --git a/pkgs/development/tools/pnpm/fetch-deps/pnpm-config-hook.sh b/pkgs/development/tools/pnpm/fetch-deps/pnpm-config-hook.sh index fbeebc8dff94..2532e5d465c1 100644 --- a/pkgs/development/tools/pnpm/fetch-deps/pnpm-config-hook.sh +++ b/pkgs/development/tools/pnpm/fetch-deps/pnpm-config-hook.sh @@ -12,10 +12,7 @@ pnpmConfigHook() { exit 1 fi - fetcherVersion=1 - if [[ -e "${pnpmDeps}/.fetcher-version" ]]; then - fetcherVersion=$(cat "${pnpmDeps}/.fetcher-version") - fi + fetcherVersion=$(cat "${pnpmDeps}/.fetcher-version" || echo 1) echo "Using fetcherVersion: $fetcherVersion" @@ -26,7 +23,12 @@ pnpmConfigHook() { export npm_config_arch="@npmArch@" export npm_config_platform="@npmPlatform@" - cp -Tr "$pnpmDeps" "$STORE_PATH" + if [[ $fetcherVersion -ge 3 ]]; then + tar --zstd -xf "$pnpmDeps/pnpm-store.tar.zst" -C "$STORE_PATH" + else + cp -Tr "$pnpmDeps" "$STORE_PATH" + fi + chmod -R +w "$STORE_PATH" diff --git a/pkgs/development/tools/pnpm/fetch-deps/serve.nix b/pkgs/development/tools/pnpm/fetch-deps/serve.nix index a60aaa3b928f..9aa5d380a0cd 100644 --- a/pkgs/development/tools/pnpm/fetch-deps/serve.nix +++ b/pkgs/development/tools/pnpm/fetch-deps/serve.nix @@ -2,6 +2,7 @@ writeShellApplication, pnpm, pnpmDeps, + zstd, }: writeShellApplication { @@ -9,11 +10,14 @@ writeShellApplication { runtimeInputs = [ pnpm + zstd ]; text = '' storePath=$(mktemp -d) + fetcherVersion=$(cat "${pnpmDeps}/.fetcher-version" || echo 1) + clean() { echo "Cleaning up temporary store at '$storePath'..." @@ -22,7 +26,12 @@ writeShellApplication { echo "Copying pnpm store '${pnpmDeps}' to temporary store..." - cp -Tr "${pnpmDeps}" "$storePath" + if [[ $fetcherVersion -ge 3 ]]; then + tar --zstd -xf "${pnpmDeps}/pnpm-store.tar.zst" -C "$storePath" + else + cp -Tr "${pnpmDeps}" "$storePath" + fi + chmod -R +w "$storePath" echo "Run 'pnpm install --store-dir \"$storePath\"' to install packages from this store."