+16
-17
@@ -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
@@ -1,6 +1,4 @@
|
|||||||
/.yarn/*
|
/.yarn
|
||||||
!/.yarn/releases
|
|
||||||
!/.yarn/plugins
|
|
||||||
/.pnp.*
|
/.pnp.*
|
||||||
|
|
||||||
/dist/yarn-plugin-nixify.dev.js
|
/dist/yarn-plugin-nixify.dev.js
|
||||||
|
|||||||
Vendored
-823
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
yarnPath: .yarn/releases/yarn-3.3.1.cjs
|
|
||||||
@@ -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
@@ -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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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)) {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user