Merge pull request #75 from stephank/feat/yarn4

Yarn v4 support
This commit is contained in:
Stéphan Kochen
2023-10-30 08:16:55 +01:00
committed by GitHub
14 changed files with 2268 additions and 2766 deletions
+16 -17
View File
@@ -11,6 +11,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: write contents: write
strategy:
matrix:
yarn_version: [3, 4]
env: env:
NIX_PATH: nixpkgs=channel:nixpkgs-unstable NIX_PATH: nixpkgs=channel:nixpkgs-unstable
steps: steps:
@@ -22,24 +25,21 @@ jobs:
with: with:
node-version: 18.x node-version: 18.x
- name: Yarn cache - name: Enable corepack
uses: actions/cache@v3 run: corepack enable
with:
path: .yarn/cache
key: yarn-${{ hashFiles('yarn.lock') }}
restore-keys: yarn-
- name: Yarn install - name: Yarn install
run: yarn install --immutable run: yarn
- name: TypeScript - name: TypeScript
if: matrix.yarn_version == 4
run: yarn check run: yarn check
- name: Build - name: Build
run: yarn build run: yarn build
- name: Update dist - name: Update dist
if: github.repository_owner == 'stephank' && github.ref == 'refs/heads/main' if: matrix.yarn_version == 4 && github.repository_owner == 'stephank' && github.ref == 'refs/heads/main'
run: | run: |
if [[ "$(git status --porcelain)" != "" ]]; then if [[ "$(git status --porcelain)" != "" ]]; then
git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
@@ -48,24 +48,20 @@ jobs:
git push git push
fi fi
- name: Set Yarn version
run: yarn set version ${{ matrix.yarn_version }}
- name: Install plugin - name: Install plugin
run: yarn plugin import ./dist/yarn-plugin-nixify.js run: yarn plugin import ./dist/yarn-plugin-nixify.js
- name: Test without Nix - name: Test without Nix
run: yarn run: yarn --no-immutable
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v23 uses: cachix/install-nix-action@v23
with: with:
nix_path: nixpkgs=channel:nixos-unstable nix_path: nixpkgs=channel:nixos-unstable
- name: Setup Cachix
if: github.event_name == 'push' && github.repository_owner == 'stephank'
uses: cachix/cachix-action@v12
with:
name: stephank
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
- name: Add bin - name: Add bin
run: | run: |
cat > hello.js << EOF cat > hello.js << EOF
@@ -82,7 +78,10 @@ jobs:
run: yarn --no-immutable run: yarn --no-immutable
- name: Test nix-build - name: Test nix-build
run: nix-build run: |
# This delete tests refetching a package with Nix.
nix-store --delete /nix/store/*--yarnpkg-core-npm-*
nix-build
- name: Test bin - name: Test bin
run: ./result/bin/hello run: ./result/bin/hello
+1 -3
View File
@@ -1,6 +1,4 @@
/.yarn/* /.yarn
!/.yarn/releases
!/.yarn/plugins
/.pnp.* /.pnp.*
/dist/yarn-plugin-nixify.dev.js /dist/yarn-plugin-nixify.dev.js
-823
View File
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
yarnPath: .yarn/releases/yarn-3.3.1.cjs
+3 -3
View File
@@ -2,7 +2,7 @@
**Upgrading the plugin? See [UPGRADING.md](./UPGRADING.md)** **Upgrading the plugin? See [UPGRADING.md](./UPGRADING.md)**
Generates a [Nix] expression to build a [Yarn] v3 project (not using Generates a [Nix] expression to build a [Yarn] v3 or v4 project (not using
zero-install). zero-install).
- Provides a `yarn` shell alias in the Nix builder — no global Yarn v1 install - Provides a `yarn` shell alias in the Nix builder — no global Yarn v1 install
@@ -43,8 +43,8 @@ Related projects:
## Usage ## Usage
The minimum version of Yarn is 3.1.0. Run the following in your project folder This plugin is compatible with Yarn >= 3.1.0 or >= 4.0.0. Run the following in
to check: your project folder to check:
```sh ```sh
# Check your Yarn version # Check your Yarn version
+11 -34
View File
@@ -8,47 +8,24 @@
"build-dev": "./build.js", "build-dev": "./build.js",
"fmt": "prettier --write src" "fmt": "prettier --write src"
}, },
"packageManager": "yarn@3.3.1", "packageManager": "yarn@4.0.1",
"devDependencies": { "devDependencies": {
"@babel/core": "^7.11.4", "@babel/core": "^7.11.4",
"@babel/plugin-proposal-class-properties": "^7.10.4", "@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/plugin-proposal-decorators": "^7.10.5", "@babel/plugin-proposal-decorators": "^7.10.5",
"@babel/preset-typescript": "^7.10.4", "@babel/preset-typescript": "^7.10.4",
"@types/node": "10", "@types/node": "10",
"@yarnpkg/cli": "^3.0.0", "@yarnpkg/cli": "^4.0.0",
"@yarnpkg/core": "^3.0.0", "@yarnpkg/core": "^4.0.0",
"@yarnpkg/fslib": "^2.5.1", "@yarnpkg/fslib": "^3.0.0",
"@yarnpkg/plugin-patch": "^3.0.0", "@yarnpkg/plugin-patch": "^4.0.0",
"@yarnpkg/plugin-pnp": "^3.1.0", "@yarnpkg/plugin-pnp": "^4.0.0",
"babel-loader": "^8.1.0", "babel-loader": "^9.1.3",
"clipanion": "^3.0.0", "clipanion": "^4.0.0-rc.2",
"prettier": "2.5.1", "prettier": "3.0.3",
"raw-loader": "^4.0.1", "raw-loader": "^4.0.1",
"typescript": "4.5.4", "typescript": "5.2.2",
"webpack": "^5.35.0", "webpack": "^5.35.0",
"webpack-sources": "^2.2.0" "webpack-sources": "^3.2.3"
},
"resolutions": {
"@yarnpkg/cli": "3.1.0",
"@yarnpkg/core": "3.1.0",
"@yarnpkg/fslib": "2.5.1",
"@yarnpkg/libzip": "2.2.2",
"@yarnpkg/plugin-compat": "3.0.0",
"@yarnpkg/plugin-dlx": "3.0.0",
"@yarnpkg/plugin-essentials": "3.0.0",
"@yarnpkg/plugin-file": "2.2.1",
"@yarnpkg/plugin-git": "2.4.0",
"@yarnpkg/plugin-github": "2.2.0",
"@yarnpkg/plugin-http": "2.1.3",
"@yarnpkg/plugin-init": "3.0.0",
"@yarnpkg/plugin-link": "2.1.2",
"@yarnpkg/plugin-node-modules": "2.3.0",
"@yarnpkg/plugin-npm": "2.5.0",
"@yarnpkg/plugin-npm-cli": "3.0.0",
"@yarnpkg/plugin-pack": "3.0.0",
"@yarnpkg/plugin-patch": "3.0.0",
"@yarnpkg/plugin-pnp": "3.1.0",
"@yarnpkg/plugin-stage": "3.0.0",
"@yarnpkg/shell": "3.0.0"
} }
} }
+2 -2
View File
@@ -18,7 +18,7 @@ export default class FetchOneCommand extends Command<CommandContext> {
async execute() { async execute() {
const configuration = await Configuration.find( const configuration = await Configuration.find(
this.context.cwd, this.context.cwd,
this.context.plugins this.context.plugins,
); );
const { project } = await Project.find(configuration, this.context.cwd); const { project } = await Project.find(configuration, this.context.cwd);
const cache = await Cache.find(configuration); const cache = await Cache.find(configuration);
@@ -42,7 +42,7 @@ export default class FetchOneCommand extends Command<CommandContext> {
fetcher, fetcher,
report, report,
}); });
} },
); );
return report.exitCode(); return report.exitCode();
+9 -9
View File
@@ -23,7 +23,7 @@ export default class InjectBuildCommand extends Command<CommandContext> {
async execute() { async execute() {
const configuration = await Configuration.find( const configuration = await Configuration.find(
this.context.cwd, this.context.cwd,
this.context.plugins this.context.plugins,
); );
const { project } = await Project.find(configuration, this.context.cwd); const { project } = await Project.find(configuration, this.context.cwd);
@@ -48,7 +48,7 @@ export default class InjectBuildCommand extends Command<CommandContext> {
// the read-only permissions of our source path in the Nix store. // the read-only permissions of our source path in the Nix store.
const installLocation = ppath.join( const installLocation = ppath.join(
project.cwd, project.cwd,
this.installLocation as PortablePath this.installLocation as PortablePath,
); );
await xfs.mkdirpPromise(ppath.dirname(installLocation)); await xfs.mkdirpPromise(ppath.dirname(installLocation));
await execUtils.execvp("cp", ["-R", this.source, installLocation], { await execUtils.execvp("cp", ["-R", this.source, installLocation], {
@@ -72,7 +72,7 @@ export default class InjectBuildCommand extends Command<CommandContext> {
(data: Buffer | string) => { (data: Buffer | string) => {
globalHashGenerator.update(`\0`); globalHashGenerator.update(`\0`);
globalHashGenerator.update(data); globalHashGenerator.update(data);
} },
); );
const globalHash = globalHashGenerator.digest(`hex`); const globalHash = globalHashGenerator.digest(`hex`);
@@ -86,7 +86,7 @@ export default class InjectBuildCommand extends Command<CommandContext> {
const pkg = project.storedPackages.get(locator.locatorHash); const pkg = project.storedPackages.get(locator.locatorHash);
if (typeof pkg === `undefined`) if (typeof pkg === `undefined`)
throw new Error( throw new Error(
`Assertion failed: The package should have been registered` `Assertion failed: The package should have been registered`,
); );
const builder = createHash(`sha512`); const builder = createHash(`sha512`);
@@ -97,20 +97,20 @@ export default class InjectBuildCommand extends Command<CommandContext> {
for (const descriptor of pkg.dependencies.values()) { for (const descriptor of pkg.dependencies.values()) {
const resolution = project.storedResolutions.get( const resolution = project.storedResolutions.get(
descriptor.descriptorHash descriptor.descriptorHash,
); );
if (typeof resolution === `undefined`) if (typeof resolution === `undefined`)
throw new Error( throw new Error(
`Assertion failed: The resolution (${structUtils.prettyDescriptor( `Assertion failed: The resolution (${structUtils.prettyDescriptor(
project.configuration, project.configuration,
descriptor descriptor,
)}) should have been registered` )}) should have been registered`,
); );
const dependency = project.storedPackages.get(resolution); const dependency = project.storedPackages.get(resolution);
if (typeof dependency === `undefined`) if (typeof dependency === `undefined`)
throw new Error( throw new Error(
`Assertion failed: The package should have been registered` `Assertion failed: The package should have been registered`,
); );
builder.update(getBaseHash(dependency)); builder.update(getBaseHash(dependency));
@@ -133,7 +133,7 @@ export default class InjectBuildCommand extends Command<CommandContext> {
// `yarn install` later, which should clean it up again. // `yarn install` later, which should clean it up again.
project.storedBuildState.set(pkg.locatorHash, buildHash); project.storedBuildState.set(pkg.locatorHash, buildHash);
await project.persistInstallStateFile(); await project.persistInstallStateFile();
} },
); );
return report.exitCode(); return report.exitCode();
+9 -9
View File
@@ -24,11 +24,11 @@ export default class InstallBinCommand extends Command<CommandContext> {
async execute() { async execute() {
const configuration = await Configuration.find( const configuration = await Configuration.find(
this.context.cwd, this.context.cwd,
this.context.plugins this.context.plugins,
); );
const { project, workspace } = await Project.find( const { project, workspace } = await Project.find(
configuration, configuration,
this.context.cwd this.context.cwd,
); );
const report = await StreamReport.start( const report = await StreamReport.start(
@@ -44,7 +44,7 @@ export default class InstallBinCommand extends Command<CommandContext> {
const wrapperPath = ppath.join(binDir, name as Filename); const wrapperPath = ppath.join(binDir, name as Filename);
const binaryPath = ppath.join( const binaryPath = ppath.join(
project.cwd, project.cwd,
npath.toPortablePath(binaryFile) npath.toPortablePath(binaryFile),
); );
await this.writeWrapper(wrapperPath, binaryPath, { await this.writeWrapper(wrapperPath, binaryPath, {
configuration, configuration,
@@ -56,18 +56,18 @@ export default class InstallBinCommand extends Command<CommandContext> {
await project.resolveEverything({ report, lockfileOnly: true }); await project.resolveEverything({ report, lockfileOnly: true });
const binaries = await scriptUtils.getPackageAccessibleBinaries( const binaries = await scriptUtils.getPackageAccessibleBinaries(
project.topLevelWorkspace.anchoredLocator, project.topLevelWorkspace.anchoredLocator,
{ project } { project },
); );
for (const [name, [_, binaryPath]] of binaries.entries()) { for (const [name, [_, binaryPath]] of binaries.entries()) {
const wrapperPath = ppath.join(binDir, name as Filename); const wrapperPath = ppath.join(binDir, name as Filename);
await this.writeWrapper( await this.writeWrapper(
wrapperPath, wrapperPath,
npath.toPortablePath(binaryPath), npath.toPortablePath(binaryPath),
{ configuration, project } { configuration, project },
); );
} }
} }
} },
); );
return report.exitCode(); return report.exitCode();
@@ -79,7 +79,7 @@ export default class InstallBinCommand extends Command<CommandContext> {
{ {
configuration, configuration,
project, project,
}: { configuration: Configuration; project: Project } }: { configuration: Configuration; project: Project },
) { ) {
let wrapper; let wrapper;
switch (configuration.get(`nodeLinker`)) { switch (configuration.get(`nodeLinker`)) {
@@ -88,14 +88,14 @@ export default class InstallBinCommand extends Command<CommandContext> {
const nodeOptions = []; const nodeOptions = [];
if (await xfs.existsPromise(pnpPath.cjs)) { if (await xfs.existsPromise(pnpPath.cjs)) {
nodeOptions.push( nodeOptions.push(
`--require "${npath.fromPortablePath(pnpPath.cjs)}"` `--require "${npath.fromPortablePath(pnpPath.cjs)}"`,
); );
} }
if (await xfs.existsPromise(pnpPath.esmLoader)) { if (await xfs.existsPromise(pnpPath.esmLoader)) {
nodeOptions.push( nodeOptions.push(
`--experimental-loader "${ `--experimental-loader "${
pathToFileURL(npath.fromPortablePath(pnpPath.esmLoader)).href pathToFileURL(npath.fromPortablePath(pnpPath.esmLoader)).href
}"` }"`,
); );
} }
wrapper = renderTmpl(binWrapperPnpTmpl, { wrapper = renderTmpl(binWrapperPnpTmpl, {
+66 -37
View File
@@ -1,13 +1,11 @@
import { tmpdir } from "os";
import { Filename, npath, PortablePath, ppath, xfs } from "@yarnpkg/fslib"; import { Filename, npath, PortablePath, ppath, xfs } from "@yarnpkg/fslib";
import { patchUtils } from "@yarnpkg/plugin-patch"; import { patchUtils } from "@yarnpkg/plugin-patch";
import {
computeFixedOutputStorePath,
sanitizeDerivationName,
} from "./nixUtils";
import { json, indent, renderTmpl, upperCamelize } from "./textUtils"; import { json, indent, renderTmpl, upperCamelize } from "./textUtils";
import { import {
Cache, Cache,
YarnVersion,
execUtils, execUtils,
hashUtils, hashUtils,
InstallMode, InstallMode,
@@ -20,12 +18,17 @@ import {
import defaultExprTmpl from "./tmpl/default.nix.in"; import defaultExprTmpl from "./tmpl/default.nix.in";
import projectExprTmpl from "./tmpl/yarn-project.nix.in"; import projectExprTmpl from "./tmpl/yarn-project.nix.in";
import { tmpdir } from "os"; import {
computeFixedOutputStorePath,
sanitizeDerivationName,
} from "./nixUtils";
const isYarn3 = YarnVersion?.startsWith("3.") || false;
// Generator function that runs after `yarn install`. // Generator function that runs after `yarn install`.
export default async ( export default async (
project: Project, project: Project,
opts: { cache: Cache; report: Report; mode?: InstallMode } opts: { cache: Cache; report: Report; mode?: InstallMode },
) => { ) => {
const { configuration, cwd } = project; const { configuration, cwd } = project;
const { cache, report } = opts; const { cache, report } = opts;
@@ -40,7 +43,7 @@ export default async (
if (project.cwd.startsWith(tempDir)) { if (project.cwd.startsWith(tempDir)) {
report.reportInfo( report.reportInfo(
0, 0,
`Skipping Nixify, because ${project.cwd} appears to be a temporary directory` `Skipping Nixify, because ${project.cwd} appears to be a temporary directory`,
); );
return; return;
} }
@@ -49,15 +52,27 @@ export default async (
const nixExprPath = configuration.get(`nixExprPath`); const nixExprPath = configuration.get(`nixExprPath`);
const yarnPathAbs = configuration.get(`yarnPath`); const yarnPathAbs = configuration.get(`yarnPath`);
let yarnPathExpr: string; let yarnBinExpr: string;
if (yarnPathAbs.startsWith(cwd)) { if (yarnPathAbs === null) {
yarnPathExpr = // Assume the current running script is the correct Yarn.
const hexHash = await hashUtils.checksumFile(
process.argv[1] as PortablePath,
);
const sriHash = "sha512-" + Buffer.from(hexHash, "hex").toString("base64");
yarnBinExpr = [
"fetchurl {",
` url = "https://repo.yarnpkg.com/${YarnVersion!}/packages/yarnpkg-cli/bin/yarn.js";`,
` hash = "${sriHash}";`,
"}",
].join("\n ");
} else if (yarnPathAbs.startsWith(cwd)) {
yarnBinExpr =
"./" + ppath.relative(ppath.dirname(nixExprPath), yarnPathAbs); "./" + ppath.relative(ppath.dirname(nixExprPath), yarnPathAbs);
} else { } else {
yarnPathExpr = json(yarnPathAbs); yarnBinExpr = json(yarnPathAbs);
report.reportWarning( report.reportWarning(
0, 0,
`The Yarn path ${yarnPathAbs} is outside the project - it may not be reachable by the Nix build` `The Yarn path ${yarnPathAbs} is outside the project - it may not be reachable by the Nix build`,
); );
} }
@@ -65,9 +80,11 @@ export default async (
let cacheFolderExpr: string; let cacheFolderExpr: string;
if (cacheFolderAbs.startsWith(cwd)) { if (cacheFolderAbs.startsWith(cwd)) {
cacheFolderExpr = json(ppath.relative(cwd, cacheFolderAbs)); cacheFolderExpr = json(ppath.relative(cwd, cacheFolderAbs));
} else if (!isYarn3 && configuration.get(`enableGlobalCache`)) {
cacheFolderExpr = '".yarn/cache"';
} else { } else {
throw Error( throw Error(
`The cache folder ${cacheFolderAbs} is outside the project, this is currently not supported` `The cache folder ${cacheFolderAbs} is outside the project, this is currently not supported`,
); );
} }
@@ -84,7 +101,7 @@ export default async (
if (!relativeSource.startsWith(cwd)) { if (!relativeSource.startsWith(cwd)) {
report.reportWarning( report.reportWarning(
0, 0,
`The config file ${source} is outside the project - it may not be reachable by the Nix build` `The config file ${source} is outside the project - it may not be reachable by the Nix build`,
); );
} }
} }
@@ -93,12 +110,13 @@ export default async (
"./" + "./" +
ppath.relative( ppath.relative(
ppath.dirname(nixExprPath), ppath.dirname(nixExprPath),
ppath.resolve(cwd, 'yarn.lock' as PortablePath) ppath.resolve(cwd, "yarn.lock" as PortablePath),
); );
// Build a list of cache entries so Nix can fetch them. // Build a list of cache entries so Nix can fetch them.
// TODO: See if we can use Nix fetchurl for npm: dependencies. // TODO: See if we can use Nix fetchurl for npm: dependencies.
interface CacheEntry { interface CacheEntry {
originalFilename: Filename;
filename: Filename; filename: Filename;
sha512: string; sha512: string;
} }
@@ -109,7 +127,9 @@ export default async (
for (const pkg of project.storedPackages.values()) { for (const pkg of project.storedPackages.values()) {
const { locatorHash } = pkg; const { locatorHash } = pkg;
const checksum = project.storedChecksums.get(locatorHash); const checksum = project.storedChecksums.get(locatorHash);
const cachePath = cache.getLocatorPath(pkg, checksum || null, cacheOptions); const cachePath = isYarn3
? (cache as any).getLocatorPath(pkg, checksum || null, cacheOptions)
: cache.getLocatorPath(pkg, checksum || null);
if (!cachePath) continue; if (!cachePath) continue;
const filename = ppath.basename(cachePath); const filename = ppath.basename(cachePath);
@@ -119,7 +139,13 @@ export default async (
const sha512 = checksum const sha512 = checksum
? checksum.split(`/`).pop()! ? checksum.split(`/`).pop()!
: await hashUtils.checksumFile(cachePath); : await hashUtils.checksumFile(cachePath);
cacheEntries.set(locatorStr, { filename, sha512 }); cacheEntries.set(locatorStr, {
originalFilename: filename,
// Rebuild the filename, because the cache file we're operating on may be
// from the mirror directory, which uses different naming.
filename: cache.getChecksumFilename(pkg, sha512),
sha512,
});
} }
let cacheEntriesCode = `cacheEntries = {\n`; let cacheEntriesCode = `cacheEntries = {\n`;
@@ -149,11 +175,11 @@ export default async (
if (structUtils.isVirtualLocator(pkg)) { if (structUtils.isVirtualLocator(pkg)) {
const devirtPkg = project.storedPackages.get( const devirtPkg = project.storedPackages.get(
structUtils.devirtualizeLocator(pkg).locatorHash structUtils.devirtualizeLocator(pkg).locatorHash,
); );
if (!devirtPkg) { if (!devirtPkg) {
throw Error( throw Error(
`Assertion failed: The locator should have been registered` `Assertion failed: The locator should have been registered`,
); );
} }
@@ -162,11 +188,11 @@ export default async (
if (pkg.reference.startsWith("patch:")) { if (pkg.reference.startsWith("patch:")) {
const depatchPkg = project.storedPackages.get( const depatchPkg = project.storedPackages.get(
patchUtils.parseLocator(pkg).sourceLocator.locatorHash patchUtils.parseLocator(pkg).sourceLocator.locatorHash,
); );
if (!depatchPkg) { if (!depatchPkg) {
throw Error( throw Error(
`Assertion failed: The locator should have been registered` `Assertion failed: The locator should have been registered`,
); );
} }
@@ -175,18 +201,18 @@ export default async (
for (const dependency of pkg.dependencies.values()) { for (const dependency of pkg.dependencies.values()) {
const resolution = project.storedResolutions.get( const resolution = project.storedResolutions.get(
dependency.descriptorHash dependency.descriptorHash,
); );
if (!resolution) { if (!resolution) {
throw Error( throw Error(
"Assertion failed: The descriptor should have been registered" "Assertion failed: The descriptor should have been registered",
); );
} }
const depPkg = project.storedPackages.get(resolution); const depPkg = project.storedPackages.get(resolution);
if (!depPkg) { if (!depPkg) {
throw Error( throw Error(
`Assertion failed: The locator should have been registered` `Assertion failed: The locator should have been registered`,
); );
} }
@@ -217,13 +243,13 @@ export default async (
ppath.join( ppath.join(
pnpUnpluggedFolder, pnpUnpluggedFolder,
structUtils.slugifyLocator(pkg), structUtils.slugifyLocator(pkg),
structUtils.getIdentVendorPath(pkg) structUtils.getIdentVendorPath(pkg),
) ),
); );
break; break;
default: default:
throw Error( throw Error(
`The nodeLinker ${nodeLinker} is not supported for isolated Nix builds` `The nodeLinker ${nodeLinker} is not supported for isolated Nix builds`,
); );
} }
@@ -236,7 +262,7 @@ export default async (
const pkg = project.storedPackages.get(locatorHash); const pkg = project.storedPackages.get(locatorHash);
if (!pkg) { if (!pkg) {
throw Error( throw Error(
`Assertion failed: The locator should have been registered` `Assertion failed: The locator should have been registered`,
); );
} }
devirtPkg = pkg; devirtPkg = pkg;
@@ -261,7 +287,7 @@ export default async (
`version = ${json(pkg.version)};`, `version = ${json(pkg.version)};`,
`reference = ${json(devirtPkg.reference)};`, `reference = ${json(devirtPkg.reference)};`,
`locators = [\n${locators}];`, `locators = [\n${locators}];`,
].join(` `)} });` ].join(` `)} });`,
); );
} }
@@ -273,7 +299,7 @@ export default async (
`yarn nixify inject-build \\`, `yarn nixify inject-build \\`,
` ${json(injectLocatorStr)} \\`, ` ${json(injectLocatorStr)} \\`,
` $\{${isolatedProp}} \\`, ` $\{${isolatedProp}} \\`,
` ${json(installLocation)}` ` ${json(installLocation)}`,
); );
} }
if (isolatedIntegration.length > 0) { if (isolatedIntegration.length > 0) {
@@ -290,7 +316,7 @@ export default async (
const projectName = ident ? structUtils.stringifyIdent(ident) : `workspace`; const projectName = ident ? structUtils.stringifyIdent(ident) : `workspace`;
const projectExpr = renderTmpl(projectExprTmpl, { const projectExpr = renderTmpl(projectExprTmpl, {
PROJECT_NAME: json(projectName), PROJECT_NAME: json(projectName),
YARN_PATH: yarnPathExpr, YARN_BIN: yarnBinExpr,
LOCKFILE: lockfileExpr, LOCKFILE: lockfileExpr,
CACHE_FOLDER: cacheFolderExpr, CACHE_FOLDER: cacheFolderExpr,
CACHE_ENTRIES: cacheEntriesCode, CACHE_ENTRIES: cacheEntriesCode,
@@ -308,7 +334,7 @@ export default async (
await xfs.writeFilePromise(defaultExprPath, defaultExprTmpl); await xfs.writeFilePromise(defaultExprPath, defaultExprTmpl);
report.reportInfo( report.reportInfo(
0, 0,
`A minimal default.nix was created. You may want to customize it.` `A minimal default.nix was created. You may want to customize it.`,
); );
} }
} }
@@ -321,7 +347,10 @@ export default async (
) { ) {
await xfs.mktempPromise(async (tempDir) => { await xfs.mktempPromise(async (tempDir) => {
const toPreload: PortablePath[] = []; const toPreload: PortablePath[] = [];
for (const [locator, { filename, sha512 }] of cacheEntries.entries()) { for (const [
locator,
{ originalFilename, sha512 },
] of cacheEntries.entries()) {
const name = sanitizeDerivationName(locator); const name = sanitizeDerivationName(locator);
// Check to see if the Nix store entry already exists. // Check to see if the Nix store entry already exists.
const hash = Buffer.from(sha512, "hex"); const hash = Buffer.from(sha512, "hex");
@@ -336,7 +365,7 @@ export default async (
const subdir = ppath.join(tempDir, sha512.slice(0, 7) as Filename); const subdir = ppath.join(tempDir, sha512.slice(0, 7) as Filename);
await xfs.mkdirPromise(subdir); await xfs.mkdirPromise(subdir);
const src = ppath.join(cache.cwd, filename); const src = ppath.join(cache.cwd, originalFilename);
const dst = ppath.join(subdir, name as Filename); const dst = ppath.join(subdir, name as Filename);
await xfs.copyFilePromise(src, dst); await xfs.copyFilePromise(src, dst);
@@ -355,13 +384,13 @@ export default async (
{ {
cwd: project.cwd, cwd: project.cwd,
strict: true, strict: true,
} },
); );
} }
if (numToPreload !== 0) { if (numToPreload !== 0) {
report.reportInfo( report.reportInfo(
0, 0,
`Preloaded ${numToPreload} packages into the Nix store` `Preloaded ${numToPreload} packages into the Nix store`,
); );
} }
} catch (err: any) { } catch (err: any) {
+1 -1
View File
@@ -46,7 +46,7 @@ export const computeFixedOutputStorePath = (
name: string, name: string,
hashAlgorithm: string, hashAlgorithm: string,
hash: Buffer, hash: Buffer,
storePath = `/nix/store` as PortablePath storePath = `/nix/store` as PortablePath,
) => { ) => {
const hashHex = hash.toString("hex"); const hashHex = hash.toString("hex");
+2 -2
View File
@@ -24,7 +24,7 @@ export const upperCamelize = (name: string) =>
export const indent = ( export const indent = (
prefix: string, prefix: string,
text: string, text: string,
includeEmptyLines = false includeEmptyLines = false,
): string => ): string =>
text text
.split("\n") .split("\n")
@@ -41,7 +41,7 @@ export const indent = (
*/ */
export const renderTmpl = ( export const renderTmpl = (
tmpl: string, tmpl: string,
vars: { [name: string]: string | boolean } vars: { [name: string]: string | boolean },
): string => { ): string => {
let result = tmpl; let result = tmpl;
for (const [name, value] of Object.entries(vars)) { for (const [name, value] of Object.entries(vars)) {
+11 -3
View File
@@ -6,6 +6,8 @@
let let
yarnBin = @@YARN_BIN@@;
cacheFolder = @@CACHE_FOLDER@@; cacheFolder = @@CACHE_FOLDER@@;
lockfile = @@LOCKFILE@@; lockfile = @@LOCKFILE@@;
@@ -15,7 +17,7 @@ let
# Simple stub that provides the global yarn command. # Simple stub that provides the global yarn command.
yarn = writeShellScriptBin "yarn" '' yarn = writeShellScriptBin "yarn" ''
exec '${nodejs}/bin/node' '${@@YARN_PATH@@}' "$@" exec '${nodejs}/bin/node' '${yarnBin}' "$@"
''; '';
# Common attributes between Yarn derivations. # Common attributes between Yarn derivations.
@@ -42,7 +44,7 @@ let
source $stdenv/setup source $stdenv/setup
cd "$src" cd "$src"
${buildVars} ${buildVars}
HOME="$TMP" yarn_cache_folder="$TMP" \ HOME="$TMP" yarn_enable_global_cache=false yarn_cache_folder="$TMP" \
yarn nixify fetch-one $locator yarn nixify fetch-one $locator
# Because we change the cache dir, Yarn may generate a different name. # Because we change the cache dir, Yarn may generate a different name.
mv "$TMP/$(sed 's/-[^-]*\.[^-]*$//' <<< "$outputFilename")"-* $out mv "$TMP/$(sed 's/-[^-]*\.[^-]*$//' <<< "$outputFilename")"-* $out
@@ -89,7 +91,8 @@ let
echo '{ "dependencies": { "${pname}": "${reference}" } }' > package.json echo '{ "dependencies": { "${pname}": "${reference}" } }' > package.json
install -m 0600 ${lockfile} ./yarn.lock install -m 0600 ${lockfile} ./yarn.lock
export yarn_global_folder="$TMP" export yarn_global_folder="$TMP"
export YARN_ENABLE_IMMUTABLE_INSTALLS=false export yarn_enable_global_cache=false
export yarn_enable_immutable_installs=false
yarn --immutable-cache yarn --immutable-cache
''; '';
@@ -123,6 +126,11 @@ let
# Yarn may need a writable home directory. # Yarn may need a writable home directory.
export yarn_global_folder="$TMP" export yarn_global_folder="$TMP"
# Ensure global cache is disabled. Cache must be part of our output.
touch .yarnrc.yml
sed -i -e '/^enableGlobalCache/d' .yarnrc.yml
echo 'enableGlobalCache: false' >> .yarnrc.yml
# Some node-gyp calls may call out to npm, which could fail due to an # Some node-gyp calls may call out to npm, which could fail due to an
# read-only home dir. # read-only home dir.
export HOME="$TMP" export HOME="$TMP"
+2137 -1822
View File
File diff suppressed because it is too large Load Diff