Skip to content

Commit

Permalink
add COREPACK_ENABLE_URL_VERSION_FOR_KNOWN_PM
Browse files Browse the repository at this point in the history
  • Loading branch information
aduh95 committed Jan 23, 2024
1 parent bdf13fd commit 59b947e
Show file tree
Hide file tree
Showing 49 changed files with 82 additions and 24 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ same major line. Should you need to upgrade to a new major, use an explicit
not to lookup on the remote registry for the latest version of the selected
package manager.

- `COREPACK_ENABLE_URL_VERSION_FOR_KNOWN_PM` can be set to `1` to allow use of
custom URLs to load a package manager known by Corepack (`yarn`, `npm`, and
`pnpm`).

- `COREPACK_ENABLE_NETWORK` can be set to `0` to prevent Corepack from accessing
the network (in which case you'll be responsible for hydrating the package
manager versions that will be required for the projects you'll run, using
Expand Down
48 changes: 27 additions & 21 deletions sources/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ function getPackageManagerRequestFromCli(parameter: string | undefined, context:
return null;

const [, binaryName, binaryVersion] = match;
const packageManager = context.engine.getPackageManagerFor(binaryName);
if (!packageManager)
return null;
const packageManager = context.engine.getPackageManagerFor(binaryName)!;

if (packageManager == null && binaryVersion == null) return null;

return {
packageManager,
Expand All @@ -47,28 +47,34 @@ function getPackageManagerRequestFromCli(parameter: string | undefined, context:
}

async function executePackageManagerRequest({packageManager, binaryName, binaryVersion}: PackageManagerRequest, args: Array<string>, context: Context) {
const defaultVersion = await context.engine.getDefaultVersion(packageManager);
const definition = context.engine.config.definitions[packageManager]!;

// If all leading segments match one of the patterns defined in the `transparent`
// key, we tolerate calling this binary even if the local project isn't explicitly
// configured for it, and we use the special default version if requested.
let fallbackLocator: Locator = {
name: binaryName,
reference: undefined as any,
};
let isTransparentCommand = false;
for (const transparentPath of definition.transparent.commands) {
if (transparentPath[0] === binaryName && transparentPath.slice(1).every((segment, index) => segment === args[index])) {
isTransparentCommand = true;
break;
if (packageManager != null) {
const defaultVersion = await context.engine.getDefaultVersion(packageManager);
const definition = context.engine.config.definitions[packageManager]!;

// If all leading segments match one of the patterns defined in the `transparent`
// key, we tolerate calling this binary even if the local project isn't explicitly
// configured for it, and we use the special default version if requested.
for (const transparentPath of definition.transparent.commands) {
if (transparentPath[0] === binaryName && transparentPath.slice(1).every((segment, index) => segment === args[index])) {
isTransparentCommand = true;
break;
}
}
}

const fallbackReference = isTransparentCommand
? definition.transparent.default ?? defaultVersion
: defaultVersion;
const fallbackReference = isTransparentCommand
? definition.transparent.default ?? defaultVersion
: defaultVersion;

const fallbackLocator: Locator = {
name: packageManager,
reference: fallbackReference,
};
fallbackLocator = {
name: packageManager,
reference: fallbackReference,
};
}

let descriptor: Descriptor;
try {
Expand Down
2 changes: 2 additions & 0 deletions sources/specUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export function parseSpec(raw: unknown, source: string, {enforceExactVersion = t
if (!isSupportedPackageManager(name)) {
throw new UsageError(`Unsupported package manager specification (${raw})`);
}
} else if (isSupportedPackageManager(name) && process.env.COREPACK_ENABLE_URL_VERSION_FOR_KNOWN_PM !== `1`) {
throw new UsageError(`Illegal use of URL for known package manager. Instead, select a specific version, or set COREPACK_ENABLE_URL_VERSION_FOR_KNOWN_PM=1 in your environment (${raw})`);
}


Expand Down
3 changes: 2 additions & 1 deletion tests/_runCli.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {PortablePath, npath} from '@yarnpkg/fslib';
import {spawn} from 'child_process';

export async function runCli(cwd: PortablePath, argv: Array<string>): Promise<{exitCode: number | null, stdout: string, stderr: string}> {
export async function runCli(cwd: PortablePath, argv: Array<string>, options?: Parameters<typeof spawn>[2]): Promise<{exitCode: number | null, stdout: string, stderr: string}> {
const out: Array<Buffer> = [];
const err: Array<Buffer> = [];

Expand All @@ -11,6 +11,7 @@ export async function runCli(cwd: PortablePath, argv: Array<string>): Promise<{e
const child = spawn(process.execPath, [`--no-warnings`, `-r`, require.resolve(`./recordRequests.js`), require.resolve(`../dist/corepack.js`), ...argv], {
cwd: npath.fromPortablePath(cwd),
env: process.env,
...options,
stdio: `pipe`,
});

Expand Down
49 changes: 47 additions & 2 deletions tests/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,50 @@ it(`should refuse to download a package manager if the hash doesn't match`, asyn
});
});

it.failing(`should refuse to download a known package manager from a URL`, async () => {
await xfs.mktempPromise(async cwd => {
// Package managers known by Corepack cannot be loaded from a URL.
await expect(runCli(cwd, [`yarn@https://registry.npmjs.com/yarn/-/yarn-1.22.21.tgz`, `--version`])).resolves.toMatchObject({
exitCode: 1,
stderr: ``,
stdout: /Illegal use of URL for known package manager/,
});

// Unknown package managers can be loaded from a URL.
await expect(runCli(cwd, [`corepack@https://registry.npmjs.com/corepack/-/corepack-0.24.1.tgz`, `--version`])).resolves.toMatchObject({
exitCode: 0,
stderr: ``,
stdout: `0.24.1\n`,
});
});
});

it.failing(`should refuse to download a known package manager from a URL in package.json`, async () => {
await xfs.mktempPromise(async cwd => {
// Package managers known by Corepack cannot be loaded from a URL.
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
packageManager: `yarn@https://registry.npmjs.com/yarn/-/yarn-1.22.21.tgz`,
});

await expect(runCli(cwd, [`yarn`, `--version`])).resolves.toMatchObject({
exitCode: 1,
stderr: ``,
stdout: /Illegal use of URL for known package manager/,
});

// Unknown package managers can be loaded from a URL.
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
packageManager: `corepack@https://registry.npmjs.com/corepack/-/corepack-0.24.1.tgz`,
});

await expect(runCli(cwd, [`corepack`, `--version`])).resolves.toMatchObject({
exitCode: 0,
stderr: ``,
stdout: `0.24.1\n`,
});
});
});

it(`should require a version to be specified`, async () => {
await xfs.mktempPromise(async cwd => {
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
Expand Down Expand Up @@ -89,7 +133,8 @@ const testedPackageManagers: Array<[string, string] | [string, string, string]>
for (const [name, version, expectedVersion = version.split(`+`, 1)[0]] of testedPackageManagers) {
it(`should use the right package manager version for a given project (${name}@${version})`, async () => {
await xfs.mktempPromise(async cwd => {
await expect(runCli(cwd, [`${name}@${version}`, `--version`])).resolves.toMatchObject({
const env = {...process.env, COREPACK_ENABLE_URL_VERSION_FOR_KNOWN_PM: `1`};
await expect(runCli(cwd, [`${name}@${version}`, `--version`], {env})).resolves.toMatchObject({
exitCode: 0,
stderr: ``,
stdout: `${expectedVersion}\n`,
Expand All @@ -99,7 +144,7 @@ for (const [name, version, expectedVersion = version.split(`+`, 1)[0]] of tested
packageManager: `${name}@${version}`,
});

await expect(runCli(cwd, [name, `--version`])).resolves.toMatchObject({
await expect(runCli(cwd, [name, `--version`], {env})).resolves.toMatchObject({
exitCode: 0,
stderr: ``,
stdout: `${expectedVersion}\n`,
Expand Down
File renamed without changes.
Binary file removed tests/nock/0mijz-lZ_5pF8f6tlAdbKg-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/2Vuch5EnmzPEVel1DWYfPQ-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/2bh2z3MgoMIcnxHAMev5uQ-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/2ituqIIXsQUU5l2SZSMRDQ-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/6BSdMkNfyZxTnw4r9rK5ig-1.dat
Binary file not shown.
File renamed without changes.
File renamed without changes.
Binary file removed tests/nock/6zkNeK1b_EJchZZ1iQz7GQ-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/7_ZKSRHG7OfkRvPJHYpxbQ-1.dat
Binary file not shown.
Binary file modified tests/nock/8LXMft4IyEWeaqoiynS5FA-1.dat
Binary file not shown.
File renamed without changes.
File renamed without changes.
Binary file removed tests/nock/D4fdrCUUCl7i1D6eeg49zQ-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/GSh7RCQN4e8flEL6h2lnwQ-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/K26guRbYG9vZYQwgFU5lHg-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/LU_vfrNkPzIhLrr405IpzQ-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/MVR-DPxEL7jQE9aetA791Q-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/TnyRFo6IK894n_HQkACElA-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/Vp5BnbFIGGY7ZeZMncmwMw-1.dat
Binary file not shown.
File renamed without changes.
File renamed without changes.
Binary file modified tests/nock/bNE0FYc3WlnFGzjHaIdf5A-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/cRq-o3WTbH0_0MVIM498_Q-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/oza0_71_8jb3typs-3gduw-1.dat
Binary file not shown.
Binary file added tests/nock/sogVBiC-f6IO6vTAaPDx5w-0.dat
Binary file not shown.
Binary file removed tests/nock/sogVBiC-f6IO6vTAaPDx5w-1.dat
Binary file not shown.
File renamed without changes.
Binary file removed tests/nock/tlFGXHHjkkY67GM_Uo2jmA-2.dat
Binary file not shown.
Binary file added tests/nock/zIqNSOkKydlbZyC4vpFlug-0.dat
Binary file not shown.
Binary file removed tests/nock/zIqNSOkKydlbZyC4vpFlug-1.dat
Binary file not shown.

0 comments on commit 59b947e

Please sign in to comment.