Files
yarn-plugin-nixify-patched/dist/yarn-plugin-nixify.js
T
Stéphan Kochen 2635212b77 Remove --immutable-cache in yarn install command
Since Yarn 3.1.0, some cache items no longer have checksums, mostly
derived items like patched packages. Nixify skipped these, but that has
started causing `--immutable-cache` to complain about the missing
entries.

Instead, we will have to rely on the Nix sandbox for purity, so that
Yarn only does local operations (like patching) when to fill in these
missing cache entries.
2021-12-13 16:35:27 +01:00

1 line
16 KiB
JavaScript

module.exports={name:"yarn-plugin-nixify",factory:function(e){var t;return(()=>{"use strict";var n={d:(e,t)=>{for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},o={};n.r(o),n.d(o,{default:()=>P});const i=e("@yarnpkg/core"),r=e("clipanion");class a extends r.Command{constructor(...e){super(...e),this.locator=r.Option.String()}async execute(){const e=await i.Configuration.find(this.context.cwd,this.context.plugins),{project:t}=await i.Project.find(e,this.context.cwd),n=await i.Cache.find(e),o=e.makeFetcher();return(await i.StreamReport.start({configuration:e,stdout:this.context.stdout},(async e=>{const{locatorHash:r}=i.structUtils.parseLocator(this.locator,!0),a=t.originalPackages.get(r);a?await o.fetch(a,{checksums:t.storedChecksums,project:t,cache:n,fetcher:o,report:e}):e.reportError(0,"Invalid locator")}))).exitCode()}}a.paths=[["nixify","fetch-one"]];const s=e("@yarnpkg/fslib"),c=e("crypto");class l extends r.Command{constructor(...e){super(...e),this.locator=r.Option.String(),this.source=r.Option.String(),this.installLocation=r.Option.String()}async execute(){const e=await i.Configuration.find(this.context.cwd,this.context.plugins),{project:t}=await i.Project.find(e,this.context.cwd);return(await i.StreamReport.start({configuration:e,stdout:this.context.stdout},(async n=>{await t.resolveEverything({report:n,lockfileOnly:!0});const o=i.structUtils.parseLocator(this.locator,!0),r=t.storedPackages.get(o.locatorHash);if(!r)return void n.reportError(0,"Invalid locator");const a=s.ppath.join(t.cwd,this.installLocation);await s.xfs.mkdirpPromise(s.ppath.dirname(a)),await i.execUtils.execvp("cp",["-R",this.source,a],{cwd:t.cwd,strict:!0}),await i.execUtils.execvp("chmod",["-R","u+w",a],{cwd:t.cwd,strict:!0});const l=(0,c.createHash)("sha512");l.update(process.versions.node),e.triggerHook((e=>e.globalHashGeneration),t,(e=>{l.update("\0"),l.update(e)}));const d=l.digest("hex"),p=new Map,h=e=>{let n=p.get(e.locatorHash);if(void 0!==n)return n;const o=t.storedPackages.get(e.locatorHash);if(void 0===o)throw new Error("Assertion failed: The package should have been registered");const r=(0,c.createHash)("sha512");r.update(e.locatorHash),p.set(e.locatorHash,"<recursive>");for(const e of o.dependencies.values()){const n=t.storedResolutions.get(e.descriptorHash);if(void 0===n)throw new Error(`Assertion failed: The resolution (${i.structUtils.prettyDescriptor(t.configuration,e)}) should have been registered`);const o=t.storedPackages.get(n);if(void 0===o)throw new Error("Assertion failed: The package should have been registered");r.update(h(o))}return n=r.digest("hex"),p.set(e.locatorHash,n),n},u=(0,c.createHash)("sha512").update(d).update(h(r)).update(a).digest("hex");t.storedBuildState.set(r.locatorHash,u),await t.persistInstallStateFile()}))).exitCode()}}l.paths=[["nixify","inject-build"]];const d=e("@yarnpkg/plugin-pnp"),p=JSON.stringify,h=(e,t,n=!1)=>t.split("\n").map((t=>t||n?e+t:t)).join("\n"),u=(e,t)=>{let n=e;for(const[e,o]of Object.entries(t))if("string"==typeof o&&(n=n.replace(`@@${e}@@`,o)),"boolean"==typeof o){const t=n.split("\n"),i=t.indexOf(`#@@ IF ${e}`),r=t.indexOf(`#@@ ENDIF ${e}`);-1!==i&&r>i&&(o?(t.splice(r,1),t.splice(i,1)):t.splice(i,r-i+1),n=t.join("\n"))}return n},f=["pnp","node-modules"];class g extends r.Command{constructor(...e){super(...e),this.binDir=r.Option.String()}async execute(){const e=await i.Configuration.find(this.context.cwd,this.context.plugins),{project:t,workspace:n}=await i.Project.find(e,this.context.cwd);return(await i.StreamReport.start({configuration:e,stdout:this.context.stdout},(async o=>{if(!n||0===n.manifest.bin.size)return;let i=e.get("nodeLinker");f.includes(i)||(i="node-modules",o.reportWarning(0,`The nodeLinker ${i} is not supported - executables may have trouble finding dependencies`));const r=s.npath.toPortablePath(this.binDir),a=(0,d.getPnpPath)(t).cjs;for(const[e,o]of n.manifest.bin){const n=s.ppath.join(r,e),c=s.ppath.join(t.cwd,s.npath.toPortablePath(o));let l;switch(i){case"pnp":l=u("#!/bin/sh\nexport NODE_OPTIONS=\"--require @@PNP_PATH@@\"\nexec '@@NODE_PATH@@' '@@SCRIPT_PATH@@' \"$@\"\n",{NODE_PATH:process.execPath,PNP_PATH:a,SCRIPT_PATH:c});break;case"node-modules":l=u("#!/bin/sh\nexec '@@NODE_PATH@@' '@@SCRIPT_PATH@@' \"$@\"\n",{NODE_PATH:process.execPath,SCRIPT_PATH:c});break;default:throw Error(`Assertion failed: Invalid nodeLinker ${i}`)}await s.xfs.writeFilePromise(n,l),await s.xfs.chmodPromise(n,493)}}))).exitCode()}}g.paths=[["nixify","install-bin"]];const m=e("@yarnpkg/plugin-patch"),x=(e,t)=>(0,c.createHash)(e).update(t).digest(),y=(e,t,n,o="/nix/store")=>{const i=n.toString("hex"),r=x("sha256",`fixed:out:${t}:${i}:`).toString("hex"),a=(e=>{let t="",n=[...e].reverse().map((e=>e.toString(2).padStart(8,"0"))).join("");for(;n;)t+="0123456789abcdfghijklmnpqrsvwxyz"[parseInt(n.slice(0,5),2)],n=n.slice(5);return t})(((e,t)=>{const n=Buffer.alloc(20);for(let t=0;t<e.length;t++)n[t%20]^=e[t];return n})(x("sha256",`output:out:sha256:${r}:${o}:${e}`)));return s.ppath.join(o,`${a}-${e}`)},v=e=>e.replace(/^\.+/,"").replace(/[^a-zA-Z0-9+._?=-]+/g,"-").slice(0,207)||"unknown",b=e("os"),P={commands:[a,l,g],hooks:{afterAllInstalled:async(e,t)=>{!1!==t.persistProject&&e.configuration.get("enableNixify")&&await(async(e,t,n)=>{const{configuration:o,cwd:r}=e,a=await s.xfs.realpathPromise(s.npath.toPortablePath((0,b.tmpdir)()));if(e.cwd.startsWith(a))return void n.reportInfo(0,`Skipping Nixify, because ${e.cwd} appears to be a temporary directory`);const c=o.get("yarnPath");let l=s.ppath.relative(r,c);l.startsWith("../")&&(l=c,n.reportWarning(0,`The Yarn path ${c} is outside the project - it may not be reachable by the Nix build`));const d=o.get("cacheFolder");let f=s.ppath.relative(r,d);f.startsWith("../")&&(f=d,n.reportWarning(0,`The cache folder ${d} is outside the project - it may not be reachable by the Nix build`));for(const e of o.sources.values())e.startsWith("<")||s.ppath.relative(r,e).startsWith("../")&&n.reportWarning(0,`The config file ${e} is outside the project - it may not be reachable by the Nix build`);const g=o.get("nixExprPath"),x=o.get("lockfileFilename"),P=s.ppath.relative(s.ppath.dirname(g),x),w=s.ppath.relative(s.ppath.dirname(g),l),k=new Map,$=new Set(await s.xfs.readdirPromise(t.cwd));for(const n of e.storedPackages.values()){const{locatorHash:o}=n,r=e.storedChecksums.get(o);if(!r)continue;const a=t.getLocatorPath(n,r);if(!a)continue;const c=s.ppath.basename(a);if(!$.has(c))continue;const l=i.structUtils.stringifyLocator(n),d=r.split("/").pop();k.set(l,{filename:c,sha512:d})}let T="cacheEntries = {\n";for(const[e,t]of k)T+=`${p(e)} = { ${[`filename = ${p(t.filename)};`,`sha512 = ${p(t.sha512)};`].join(" ")} };\n`;T+="};";const E=o.get("isolatedNixBuilds");let A=new Set,j=[],S=[];const N=o.get("nodeLinker"),I=o.get("pnpUnpluggedFolder"),C=(t,n=new Set)=>{const o=i.structUtils.stringifyLocator(t);if(k.has(o)&&n.add(o),i.structUtils.isVirtualLocator(t)){const o=e.storedPackages.get(i.structUtils.devirtualizeLocator(t).locatorHash);if(!o)throw Error("Assertion failed: The locator should have been registered");C(o,n)}if(t.reference.startsWith("patch:")){const o=e.storedPackages.get(m.patchUtils.parseLocator(t).sourceLocator.locatorHash);if(!o)throw Error("Assertion failed: The locator should have been registered");C(o,n)}for(const o of t.dependencies.values()){const t=e.storedResolutions.get(o.descriptorHash);if(!t)throw Error("Assertion failed: The descriptor should have been registered");const i=e.storedPackages.get(t);if(!i)throw Error("Assertion failed: The locator should have been registered");C(i,n)}return n};for(const t of e.storedBuildState.keys()){const n=e.storedPackages.get(t);if(!n)throw Error("Assertion failed: The locator should have been registered");if(!E.includes(n.name))continue;let o;switch(N){case"pnp":o=s.ppath.relative(e.cwd,s.ppath.join(I,i.structUtils.slugifyLocator(n),i.structUtils.getIdentVendorPath(n)));break;default:throw Error(`The nodeLinker ${N} is not supported for isolated Nix builds`)}let r=n;if(i.structUtils.isVirtualLocator(r)){const{locatorHash:t}=i.structUtils.devirtualizeLocator(r),n=e.storedPackages.get(t);if(!n)throw Error("Assertion failed: The locator should have been registered");r=n}const a=i.structUtils.stringifyLocator(r),c=i.structUtils.stringifyLocator(n),l=`isolated.${p(a)}`;if(!A.has(r)){A.add(r);const e=[...C(n)].sort().map((e=>`${p(e)}\n`)).join(""),t=`override${O=n.name,O.split(/[^a-zA-Z0-9]+/g).filter((e=>e)).map((e=>{return(t=e).slice(0,1).toUpperCase()+t.slice(1);var t})).join("")}Attrs`;S.push(`${l} = optionalOverride (args.${t} or null) (mkIsolatedBuild { ${[`pname = ${p(n.name)};`,`version = ${p(n.version)};`,`locators = [\n${e}];`].join(" ")} });`)}0===j.length&&j.push("# Copy in isolated builds."),j.push(`echo 'injecting build for ${n.name}'`,"yarn nixify inject-build \\",` ${p(c)} \\`,` \${${l}} \\`,` ${p(o)}`)}var O;j.length>0&&j.push("echo 'running yarn install'");const _=e.topLevelWorkspace.manifest.name,H=_?i.structUtils.stringifyIdent(_):"workspace",L=u('# This file is generated by running "yarn install" inside your project.\n# Manual changes might be lost - proceed with caution!\n\n{ lib, nodejs, stdenv, fetchurl, writeText }:\n{ src, overrideAttrs ? null, ... } @ args:\n\nlet\n\n yarnPath = ./@@YARN_PATH@@;\n lockfile = ./@@LOCKFILE@@;\n cacheFolder = @@CACHE_FOLDER@@;\n\n # Call overrideAttrs on a derivation if a function is provided.\n optionalOverride = fn: drv:\n if fn == null then drv else drv.overrideAttrs fn;\n\n # Common attributes between Yarn derivations.\n drvCommon = {\n # Make sure the build uses the right Node.js version everywhere.\n buildInputs = [ nodejs ];\n # Tell node-gyp to use the provided Node.js headers for native code builds.\n npm_config_nodedir = nodejs;\n # Tell node-pre-gyp to never fetch binaries / always build from source.\n npm_config_build_from_source = "true";\n # Defines the shell alias to run Yarn.\n postHook = \'\'\n yarn() {\n CI=1 node "${yarnPath}" "$@"\n }\n \'\';\n };\n\n # Create derivations for fetching dependencies.\n cacheDrvs = let\n builder = builtins.toFile "builder.sh" \'\'\n source $stdenv/setup\n cd "$src"\n HOME="$TMP" yarn_cache_folder="$TMP" CI=1 \\\n node \'${yarnPath}\' nixify fetch-one $locator\n mv "$TMP/$outputFilename" $out\n \'\';\n in lib.mapAttrs (locator: { filename, sha512 }: stdenv.mkDerivation {\n inherit src builder locator;\n name = lib.strings.sanitizeDerivationName locator;\n buildInputs = [ nodejs ];\n outputFilename = filename;\n outputHashMode = "flat";\n outputHashAlgo = "sha512";\n outputHash = sha512;\n }) cacheEntries;\n\n # Create a shell snippet to copy dependencies from a list of derivations.\n mkCacheBuilderForDrvs = drvs:\n writeText "collect-cache.sh" (lib.concatMapStrings (drv: \'\'\n cp ${drv} \'${drv.outputFilename}\'\n \'\') drvs);\n\n#@@ IF NEED_ISOLATED_BUILD_SUPPRORT\n # Create a shell snippet to copy dependencies from a list of locators.\n mkCacheBuilderForLocators = let\n pickCacheDrvs = map (locator: cacheDrvs.${locator});\n in locators:\n mkCacheBuilderForDrvs (pickCacheDrvs locators);\n\n # Create a derivation that builds a node-pre-gyp module in isolation.\n mkIsolatedBuild = { pname, version, locators }: stdenv.mkDerivation (drvCommon // {\n inherit pname version;\n phases = [ "buildPhase" "installPhase" ];\n\n buildPhase = \'\'\n mkdir -p .yarn/cache\n pushd .yarn/cache > /dev/null\n source ${mkCacheBuilderForLocators locators}\n popd > /dev/null\n\n echo \'{ "dependencies": { "${pname}": "${version}" } }\' > package.json\n install -m 0600 ${lockfile} ./yarn.lock\n export yarn_global_folder="$TMP"\n export YARN_ENABLE_IMMUTABLE_INSTALLS=false\n yarn\n \'\';\n\n installPhase = \'\'\n unplugged=( .yarn/unplugged/${pname}-*/node_modules/* )\n if [[ ! -e "\'\'${unplugged[@]}" ]]; then\n echo >&2 "Could not find the unplugged path for ${pname}"\n exit 1\n fi\n\n mv "$unplugged" $out\n \'\';\n });\n#@@ ENDIF NEED_ISOLATED_BUILD_SUPPRORT\n\n # Main project derivation.\n project = stdenv.mkDerivation (drvCommon // {\n inherit src;\n name = @@PROJECT_NAME@@;\n # Disable Nixify plugin to save on some unnecessary processing.\n yarn_enable_nixify = "false";\n\n configurePhase = \'\'\n runHook preConfigure\n\n # Copy over the Yarn cache.\n rm -fr \'${cacheFolder}\'\n mkdir -p \'${cacheFolder}\'\n pushd \'${cacheFolder}\' > /dev/null\n source ${mkCacheBuilderForDrvs (lib.attrValues cacheDrvs)}\n popd > /dev/null\n\n # Yarn may need a writable home directory.\n export yarn_global_folder="$TMP"\n\n@@ISOLATED_INTEGRATION@@\n\n # Run normal Yarn install to complete dependency installation.\n yarn install --immutable\n\n runHook postConfigure\n \'\';\n\n buildPhase = \'\'\n runHook preBuild\n runHook postBuild\n \'\';\n\n installPhase = \'\'\n runHook preInstall\n\n mkdir -p $out/libexec $out/bin\n\n # Move the entire project to the output directory.\n mv $PWD "$out/libexec/$sourceRoot"\n cd "$out/libexec/$sourceRoot"\n\n # Invoke a plugin internal command to setup binaries.\n yarn nixify install-bin $out/bin\n\n runHook postInstall\n \'\';\n\n passthru = {\n inherit nodejs;\n };\n });\n\n@@CACHE_ENTRIES@@\n@@ISOLATED@@\nin optionalOverride overrideAttrs project\n',{PROJECT_NAME:p(H),YARN_PATH:w,LOCKFILE:P,CACHE_FOLDER:p(f),CACHE_ENTRIES:T,ISOLATED:S.join("\n"),ISOLATED_INTEGRATION:h(" ",j.join("\n")),NEED_ISOLATED_BUILD_SUPPRORT:j.length>0});if(await s.xfs.writeFilePromise(o.get("nixExprPath"),L),o.get("generateDefaultNix")){const e=s.ppath.join(r,"default.nix"),t=s.ppath.join(r,"flake.nix");s.xfs.existsSync(e)||s.xfs.existsSync(t)||(await s.xfs.writeFilePromise(e,"# This is a minimal `default.nix` by yarn-plugin-nixify. You can customize it\n# as needed, it will not be overwritten by the plugin.\n\n{ pkgs ? import <nixpkgs> { } }:\n\npkgs.callPackage ./yarn-project.nix { } { src = ./.; }\n"),n.reportInfo(0,"A minimal default.nix was created. You may want to customize it."))}o.get("enableNixPreload")&&s.xfs.existsSync(s.npath.toPortablePath("/nix/store"))&&await s.xfs.mktempPromise((async o=>{const r=[];for(const[e,{filename:n,sha512:i}]of k.entries()){const a=v(e),c=Buffer.from(i,"hex"),l=y(a,"sha512",c);if(!s.xfs.existsSync(l)){const e=s.ppath.join(o,i.slice(0,7));await s.xfs.mkdirPromise(e);const c=s.ppath.join(t.cwd,n),l=s.ppath.join(e,a);await s.xfs.copyFilePromise(c,l),r.push(l)}}try{const t=r.length;for(;0!==r.length;){const t=r.splice(0,100);await i.execUtils.execvp("nix-store",["--add-fixed","sha512",...t],{cwd:e.cwd,strict:!0})}0!==t&&n.reportInfo(0,`Preloaded ${t} packages into the Nix store`)}catch(e){if("ENOENT"!==e.code)throw e}}))})(e,t.cache,t.report)}},configuration:{enableNixify:{description:"If false, disables the Nixify plugin hook that generates Nix expressions",type:i.SettingsType.BOOLEAN,default:!0},nixExprPath:{description:"Path of the file where the project Nix expression will be written to",type:i.SettingsType.ABSOLUTE_PATH,default:"./yarn-project.nix"},generateDefaultNix:{description:"If true, a default.nix will be generated if it does not exist",type:i.SettingsType.BOOLEAN,default:!0},enableNixPreload:{description:"If true, cached packages will be preloaded into the Nix store",type:i.SettingsType.BOOLEAN,default:!0},isolatedNixBuilds:{description:"Dependencies with a build step that can be built in an isolated derivation",type:i.SettingsType.STRING,default:[],isArray:!0}}};t=o})(),t}};