mirror of https://github.com/nodejs/corepack.git
Implements enable / disable (#11)
* Implements enable / disable * Adds tests * Debugs GH-only crash * Fixes CI by running the build beforehand * Fixes build
This commit is contained in:
parent
b56df30796
commit
1a3db689dc
|
|
@ -0,0 +1,16 @@
|
|||
# EditorConfig is awesome!
|
||||
|
||||
# Mark this as the root editorconfig file
|
||||
root = true
|
||||
|
||||
# Base ruleset for all files
|
||||
[*]
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# Override rules for markdown
|
||||
[*.md]
|
||||
# trailing whitespace is significant in markdown -> do not remove
|
||||
trim_trailing_whitespace = false
|
||||
|
|
@ -23,5 +23,6 @@ jobs:
|
|||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- run: yarn install --immutable
|
||||
- run: yarn build # We need the stubs to run the tests
|
||||
- run: yarn eslint
|
||||
- run: yarn jest
|
||||
|
|
@ -47,6 +47,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
["@types/node", "npm:13.9.2"],
|
||||
["@types/semver", "npm:7.1.0"],
|
||||
["@types/tar", "npm:4.0.3"],
|
||||
["@types/which", "npm:1.3.2"],
|
||||
["@typescript-eslint/eslint-plugin", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:2.34.0"],
|
||||
["@typescript-eslint/parser", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:4.2.0"],
|
||||
["@yarnpkg/eslint-config", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:0.1.0"],
|
||||
|
|
@ -66,7 +67,8 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
["ts-node", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:8.10.2"],
|
||||
["typescript", "patch:typescript@npm%3A3.9.7#builtin<compat/typescript>::version=3.9.7&hash=5b02a2"],
|
||||
["webpack", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:5.0.0-beta.23"],
|
||||
["webpack-cli", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:3.3.11"]
|
||||
["webpack-cli", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:3.3.11"],
|
||||
["which", "npm:2.0.2"]
|
||||
],
|
||||
"linkType": "SOFT",
|
||||
}]
|
||||
|
|
@ -1176,6 +1178,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["@types/which", [
|
||||
["npm:1.3.2", {
|
||||
"packageLocation": "./.yarn/cache/@types-which-npm-1.3.2-7f927243ae-ffb779f93f.zip/node_modules/@types/which/",
|
||||
"packageDependencies": [
|
||||
["@types/which", "npm:1.3.2"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["@types/yargs", [
|
||||
["npm:15.0.4", {
|
||||
"packageLocation": "./.yarn/cache/@types-yargs-npm-15.0.4-4311b7c654-03117288be.zip/node_modules/@types/yargs/",
|
||||
|
|
@ -2565,6 +2576,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
["@types/node", "npm:13.9.2"],
|
||||
["@types/semver", "npm:7.1.0"],
|
||||
["@types/tar", "npm:4.0.3"],
|
||||
["@types/which", "npm:1.3.2"],
|
||||
["@typescript-eslint/eslint-plugin", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:2.34.0"],
|
||||
["@typescript-eslint/parser", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:4.2.0"],
|
||||
["@yarnpkg/eslint-config", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:0.1.0"],
|
||||
|
|
@ -2584,7 +2596,8 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
["ts-node", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:8.10.2"],
|
||||
["typescript", "patch:typescript@npm%3A3.9.7#builtin<compat/typescript>::version=3.9.7&hash=5b02a2"],
|
||||
["webpack", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:5.0.0-beta.23"],
|
||||
["webpack-cli", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:3.3.11"]
|
||||
["webpack-cli", "virtual:0bda696f47fa4339976f909c007f0dc954386da51b8923bf264010d9929618071aa538c29b76d4b6c53f7388a7d83508f2a5027eb81cfc74b39b9d4a0b1a8c5a#npm:3.3.11"],
|
||||
["which", "npm:2.0.2"]
|
||||
],
|
||||
"linkType": "SOFT",
|
||||
}]
|
||||
|
|
|
|||
|
|
@ -5,5 +5,9 @@
|
|||
"**/.pnp.*": true
|
||||
},
|
||||
"eslint.nodePath": ".yarn/sdks",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": true,
|
||||
"source.fixAll.eslint": true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -20,6 +20,7 @@
|
|||
"@types/node": "^13.9.2",
|
||||
"@types/semver": "^7.1.0",
|
||||
"@types/tar": "^4.0.3",
|
||||
"@types/which": "^1.3.2",
|
||||
"@typescript-eslint/eslint-plugin": "^2.0.0",
|
||||
"@typescript-eslint/parser": "^4.2.0",
|
||||
"@yarnpkg/eslint-config": "^0.1.0",
|
||||
|
|
@ -39,13 +40,15 @@
|
|||
"ts-node": "^8.10.2",
|
||||
"typescript": "^3.9.7",
|
||||
"webpack": "next",
|
||||
"webpack-cli": "^3.3.11"
|
||||
"webpack-cli": "^3.3.11",
|
||||
"which": "^2.0.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -rf dist && webpack && ts-node ./mkshims.ts",
|
||||
"corepack": "ts-node ./sources/main.ts",
|
||||
"prepack": "node ./.yarn/releases/*.*js build",
|
||||
"postpack": "rm -rf dist shims"
|
||||
"postpack": "rm -rf dist shims",
|
||||
"test": "yarn jest"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
|
|
|
|||
|
|
@ -1,17 +1,34 @@
|
|||
import {UsageError} from 'clipanion';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
import {UsageError} from 'clipanion';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
|
||||
import defaultConfig from '../config.json';
|
||||
import defaultConfig from '../config.json';
|
||||
|
||||
import * as folderUtils from './folderUtils';
|
||||
import * as pmmUtils from './pmmUtils';
|
||||
import {Config, Descriptor, Locator, SupportedPackageManagers, SupportedPackageManagerSet} from './types';
|
||||
import * as folderUtils from './folderUtils';
|
||||
import * as pmmUtils from './pmmUtils';
|
||||
import {SupportedPackageManagers, SupportedPackageManagerSet} from './types';
|
||||
import {Config, Descriptor, Locator} from './types';
|
||||
|
||||
|
||||
export class Engine {
|
||||
constructor(private config: Config = defaultConfig as Config) {
|
||||
constructor(public config: Config = defaultConfig as Config) {
|
||||
}
|
||||
|
||||
getBinariesFor(name: SupportedPackageManagers) {
|
||||
const binNames = new Set<string>();
|
||||
|
||||
for (const rangeDefinition of Object.values(this.config.definitions[name]!.ranges)) {
|
||||
const bins = Array.isArray(rangeDefinition.bin)
|
||||
? rangeDefinition.bin
|
||||
: Object.keys(rangeDefinition.bin);
|
||||
|
||||
for (const name of bins) {
|
||||
binNames.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
return binNames;
|
||||
}
|
||||
|
||||
async getDefaultDescriptors() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
import {Command, UsageError} from 'clipanion';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import which from 'which';
|
||||
|
||||
import {Context} from '../main';
|
||||
import {isSupportedPackageManager, SupportedPackageManagerSet} from '../types';
|
||||
|
||||
export class DisableCommand extends Command<Context> {
|
||||
static usage = Command.Usage({
|
||||
description: `Remove the Corepack shims from the install directory`,
|
||||
details: `
|
||||
When run, this command will remove the shims for the specified package managers from the install directory, or all shims if no parameters are passed.
|
||||
|
||||
By default it will locate the install directory by running the equivalent of \`which corepack\`, but this can be tweaked by explicitly passing the install directory via the \`--bin-folder\` flag.
|
||||
`,
|
||||
examples: [[
|
||||
`Disable all shims, removing them if they're next to the \`coreshim\` binary`,
|
||||
`$0 disable`,
|
||||
], [
|
||||
`Disable all shims, removing them from the specified directory`,
|
||||
`$0 disable --install-directory /path/to/bin`,
|
||||
], [
|
||||
`Disable the Yarn shim only`,
|
||||
`$0 disable yarn`,
|
||||
]],
|
||||
});
|
||||
|
||||
@Command.String(`--install-directory`)
|
||||
installDirectory?: string;
|
||||
|
||||
@Command.Rest()
|
||||
names: Array<string> = [];
|
||||
|
||||
@Command.Path(`disable`)
|
||||
async execute() {
|
||||
let installDirectory = this.installDirectory;
|
||||
|
||||
// Node always call realpath on the module it executes, so we already
|
||||
// lost track of how the binary got called. To find it back, we need to
|
||||
// iterate over the PATH variable.
|
||||
if (typeof installDirectory === `undefined`)
|
||||
installDirectory = path.dirname(await which(`corepack`));
|
||||
|
||||
if (process.platform === `win32`) {
|
||||
return this.executeWin32(installDirectory);
|
||||
} else {
|
||||
return this.executePosix(installDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
async executePosix(installDirectory: string) {
|
||||
const names = this.names.length === 0
|
||||
? SupportedPackageManagerSet
|
||||
: this.names;
|
||||
|
||||
for (const name of new Set(names)) {
|
||||
if (!isSupportedPackageManager(name))
|
||||
throw new UsageError(`Invalid package manager name '${name}'`);
|
||||
|
||||
for (const binName of this.context.engine.getBinariesFor(name)) {
|
||||
const file = path.join(installDirectory, binName);
|
||||
try {
|
||||
await fs.promises.unlink(file);
|
||||
} catch (err) {
|
||||
if (err.code !== `ENOENT`) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async executeWin32(installDirectory: string) {
|
||||
throw new UsageError(`This command isn't available on Windows at this time`);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
import {Command, UsageError} from 'clipanion';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import which from 'which';
|
||||
|
||||
import {Context} from '../main';
|
||||
import {isSupportedPackageManager, SupportedPackageManagerSet} from '../types';
|
||||
|
||||
export class EnableCommand extends Command<Context> {
|
||||
static usage = Command.Usage({
|
||||
description: `Add the Corepack shims to the install directories`,
|
||||
details: `
|
||||
When run, this commmand will check whether the shims for the specified package managers can be found with the correct values inside the install directory. If not, or if they don't exist, they will be created.
|
||||
|
||||
By default it will locate the install directory by running the equivalent of \`which corepack\`, but this can be tweaked by explicitly passing the install directory via the \`--bin-folder\` flag.
|
||||
`,
|
||||
examples: [[
|
||||
`Enable all shims, putting them next to the \`corepath\` binary`,
|
||||
`$0 enable`,
|
||||
], [
|
||||
`Enable all shims, putting them in the specified directory`,
|
||||
`$0 enable --bin-folder /path/to/folder`,
|
||||
], [
|
||||
`Enable the Yarn shim only`,
|
||||
`$0 enable yarn`,
|
||||
]],
|
||||
});
|
||||
|
||||
@Command.String(`--install-directory`)
|
||||
installDirectory?: string;
|
||||
|
||||
@Command.Rest()
|
||||
names: Array<string> = [];
|
||||
|
||||
@Command.Path(`enable`)
|
||||
async execute() {
|
||||
let installDirectory = this.installDirectory;
|
||||
|
||||
// Node always call realpath on the module it executes, so we already
|
||||
// lost track of how the binary got called. To find it back, we need to
|
||||
// iterate over the PATH variable.
|
||||
if (typeof installDirectory === `undefined`)
|
||||
installDirectory = path.dirname(await which(`corepack`));
|
||||
|
||||
if (process.platform === `win32`) {
|
||||
return this.executeWin32(installDirectory);
|
||||
} else {
|
||||
return this.executePosix(installDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
async executePosix(installDirectory: string) {
|
||||
// We use `eval` so that Webpack doesn't statically transform it.
|
||||
const manifestPath = eval(`require`).resolve(`corepack/package.json`);
|
||||
|
||||
const stubFolder = path.join(path.dirname(manifestPath), `shims`);
|
||||
if (!fs.existsSync(stubFolder))
|
||||
throw new Error(`Assertion failed: The stub folder doesn't exist`);
|
||||
|
||||
const names = this.names.length === 0
|
||||
? SupportedPackageManagerSet
|
||||
: this.names;
|
||||
|
||||
for (const name of new Set(names)) {
|
||||
if (!isSupportedPackageManager(name))
|
||||
throw new UsageError(`Invalid package manager name '${name}'`);
|
||||
|
||||
for (const binName of this.context.engine.getBinariesFor(name)) {
|
||||
const file = path.join(installDirectory, binName);
|
||||
const symlink = path.relative(installDirectory, path.join(stubFolder, binName));
|
||||
|
||||
if (fs.existsSync(file)) {
|
||||
const currentSymlink = await fs.promises.readlink(file);
|
||||
if (currentSymlink !== symlink) {
|
||||
await fs.promises.unlink(file);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await fs.promises.symlink(symlink, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async executeWin32(target: string) {
|
||||
throw new UsageError(`This command isn't available on Windows at this time`);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,8 +10,8 @@ export class HydrateCommand extends Command<Context> {
|
|||
static usage = Command.Usage({
|
||||
description: `Import a package manager into the cache`,
|
||||
details: `
|
||||
This command unpacks a package manager archive into the cache. The archive must have been generated by the \`corepack pack\` command - no other will work.
|
||||
`,
|
||||
This command unpacks a package manager archive into the cache. The archive must have been generated by the \`corepack pack\` command - no other will work.
|
||||
`,
|
||||
examples: [[
|
||||
`Import a package manager in the cache`,
|
||||
`$0 hydrate corepack-yarn-2.2.2.tgz`,
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ export class PrepareCommand extends Command<Context> {
|
|||
static usage = Command.Usage({
|
||||
description: `Generate a package manager archive`,
|
||||
details: `
|
||||
This command generates an archive for the specified package manager, in a format suitable for later hydratation via the \`corepack hydrate\` command.
|
||||
This command generates an archive for the specified package manager, in a format suitable for later hydratation via the \`corepack hydrate\` command.
|
||||
|
||||
If run without parameter, it'll extract the package manager spec from the active project. Otherwise an explicit spec string is required, that Corepack will resolve before installing and packing.
|
||||
`,
|
||||
If run without parameter, it'll extract the package manager spec from the active project. Otherwise an explicit spec string is required, that Corepack will resolve before installing and packing.
|
||||
`,
|
||||
examples: [[
|
||||
`Generate an archive from the active project`,
|
||||
`$0 prepare`,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import {BaseContext, Cli, Command, UsageError} from 'clipanion';
|
||||
|
||||
import {Engine} from './Engine';
|
||||
import {DisableCommand} from './commands/Disable';
|
||||
import {EnableCommand} from './commands/Enable';
|
||||
import {HydrateCommand} from './commands/Hydrate';
|
||||
import {PrepareCommand} from './commands/Prepare';
|
||||
import * as miscUtils from './miscUtils';
|
||||
|
|
@ -69,6 +71,8 @@ export async function main(argv: Array<string>, context: CustomContext & Partial
|
|||
|
||||
cli.register(Command.Entries.Help as any);
|
||||
|
||||
cli.register(EnableCommand);
|
||||
cli.register(DisableCommand);
|
||||
cli.register(HydrateCommand);
|
||||
cli.register(PrepareCommand);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import {UsageError} from 'clipanion';
|
||||
import Enquirer from 'enquirer';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
import {UsageError} from 'clipanion';
|
||||
import Enquirer from 'enquirer';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
|
||||
import * as miscUtils from './miscUtils';
|
||||
import {SupportedPackageManagers, SupportedPackageManagerSet, Descriptor, Locator} from './types';
|
||||
import * as miscUtils from './miscUtils';
|
||||
import {Descriptor, Locator, isSupportedPackageManager} from './types';
|
||||
|
||||
export function parseSpec(raw: unknown, source?: string): Descriptor {
|
||||
if (typeof raw !== `string`)
|
||||
|
|
@ -15,11 +15,11 @@ export function parseSpec(raw: unknown, source?: string): Descriptor {
|
|||
if (match === null || !semver.validRange(match[2]))
|
||||
throw new UsageError(`Invalid package manager specification in ${source}; expected a semver range`);
|
||||
|
||||
if (!SupportedPackageManagerSet.has(match[1]))
|
||||
if (!isSupportedPackageManager(match[1]))
|
||||
throw new UsageError(`Unsupported package manager specification (${match})`);
|
||||
|
||||
return {
|
||||
name: match[1] as SupportedPackageManagers,
|
||||
name: match[1],
|
||||
range: match[2],
|
||||
};
|
||||
}
|
||||
|
|
@ -52,16 +52,14 @@ export async function findProjectSpec(initialCwd: string, locator: Locator): Pro
|
|||
case `NoSpec`: {
|
||||
// A locator is a valid descriptor (but not the other way around)
|
||||
return {name: locator.name, range: locator.reference};
|
||||
} break;
|
||||
|
||||
}
|
||||
case `Found`: {
|
||||
if (result.spec.name !== locator.name) {
|
||||
throw new UsageError(`This project is configured to use ${result.spec.name}`);
|
||||
} else {
|
||||
return result.spec;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ export enum SupportedPackageManagers {
|
|||
Yarn = `yarn`,
|
||||
}
|
||||
|
||||
export const SupportedPackageManagerSet = new Set<string>(
|
||||
export const SupportedPackageManagerSet = new Set<SupportedPackageManagers>(
|
||||
Object.values(SupportedPackageManagers),
|
||||
);
|
||||
|
||||
export function isSupportedPackageManager(value: string): value is SupportedPackageManagers {
|
||||
return SupportedPackageManagerSet.has(value);
|
||||
return SupportedPackageManagerSet.has(value as SupportedPackageManagers);
|
||||
}
|
||||
|
||||
export interface NpmTagSpec {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
import {Filename, ppath, xfs, npath, PortablePath} from '@yarnpkg/fslib';
|
||||
import {delimiter} from 'path';
|
||||
|
||||
import {Engine} from '../sources/Engine';
|
||||
import {SupportedPackageManagerSet} from '../sources/types';
|
||||
|
||||
import {runCli} from './_runCli';
|
||||
|
||||
const engine = new Engine();
|
||||
|
||||
beforeEach(async () => {
|
||||
process.env.COREPACK_HOME = await xfs.mktempPromise();
|
||||
});
|
||||
|
||||
async function makeBin(cwd: PortablePath, name: Filename) {
|
||||
const path = ppath.join(cwd, name);
|
||||
|
||||
await xfs.writeFilePromise(path, ``);
|
||||
await xfs.chmodPromise(path, 0o755);
|
||||
}
|
||||
|
||||
describe(`DisableCommand`, () => {
|
||||
it(`should remove the binaries from the folder found in the PATH`, async () => {
|
||||
await xfs.mktempPromise(async cwd => {
|
||||
await makeBin(cwd, `corepack` as Filename);
|
||||
await makeBin(cwd, `dont-remove` as Filename);
|
||||
|
||||
for (const packageManager of SupportedPackageManagerSet)
|
||||
for (const binName of engine.getBinariesFor(packageManager))
|
||||
await makeBin(cwd, binName as Filename);
|
||||
|
||||
const PATH = process.env.PATH;
|
||||
try {
|
||||
process.env.PATH = `${npath.fromPortablePath(cwd)}${delimiter}${PATH}`;
|
||||
await expect(runCli(cwd, [`disable`])).resolves.toMatchObject({
|
||||
exitCode: 0,
|
||||
});
|
||||
} finally {
|
||||
process.env.PATH = PATH;
|
||||
}
|
||||
|
||||
const sortedEntries = xfs.readdirPromise(cwd).then(entries => {
|
||||
return entries.sort();
|
||||
});
|
||||
|
||||
await expect(sortedEntries).resolves.toEqual([
|
||||
`corepack`,
|
||||
`dont-remove`,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should remove the binaries from the specified folder when used with --install-directory`, async () => {
|
||||
await xfs.mktempPromise(async cwd => {
|
||||
await xfs.writeFilePromise(ppath.join(cwd, `dont-remove` as Filename), ``);
|
||||
|
||||
for (const packageManager of SupportedPackageManagerSet)
|
||||
for (const binName of engine.getBinariesFor(packageManager))
|
||||
await makeBin(cwd, binName as Filename);
|
||||
|
||||
await expect(runCli(cwd, [`disable`, `--install-directory`, npath.fromPortablePath(cwd)])).resolves.toMatchObject({
|
||||
exitCode: 0,
|
||||
});
|
||||
|
||||
await expect(xfs.readdirPromise(cwd)).resolves.toEqual([
|
||||
`dont-remove`,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should remove binaries only for the requested package managers`, async () => {
|
||||
await xfs.mktempPromise(async cwd => {
|
||||
const binNames = new Set<string>();
|
||||
|
||||
await makeBin(cwd, `corepack` as Filename);
|
||||
binNames.add(`corepack`);
|
||||
|
||||
await makeBin(cwd, `dont-remove` as Filename);
|
||||
binNames.add(`dont-remove`);
|
||||
|
||||
for (const packageManager of SupportedPackageManagerSet)
|
||||
for (const binName of engine.getBinariesFor(packageManager))
|
||||
binNames.add(binName);
|
||||
|
||||
for (const binName of binNames)
|
||||
await makeBin(cwd, binName as Filename);
|
||||
|
||||
const PATH = process.env.PATH;
|
||||
try {
|
||||
process.env.PATH = `${npath.fromPortablePath(cwd)}${delimiter}${PATH}`;
|
||||
await expect(runCli(cwd, [`disable`, `yarn`])).resolves.toMatchObject({
|
||||
exitCode: 0,
|
||||
});
|
||||
} finally {
|
||||
process.env.PATH = PATH;
|
||||
}
|
||||
|
||||
binNames.delete(`yarn`);
|
||||
binNames.delete(`yarnpkg`);
|
||||
|
||||
const sortedEntries = xfs.readdirPromise(cwd).then(entries => {
|
||||
return entries.sort();
|
||||
});
|
||||
|
||||
await expect(sortedEntries).resolves.toEqual([...binNames].sort());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
import {Filename, ppath, xfs, npath, PortablePath} from '@yarnpkg/fslib';
|
||||
import {delimiter} from 'path';
|
||||
|
||||
import {Engine} from '../sources/Engine';
|
||||
import {SupportedPackageManagerSet, SupportedPackageManagers} from '../sources/types';
|
||||
|
||||
import {runCli} from './_runCli';
|
||||
|
||||
const engine = new Engine();
|
||||
|
||||
beforeEach(async () => {
|
||||
process.env.COREPACK_HOME = await xfs.mktempPromise();
|
||||
});
|
||||
|
||||
async function makeBin(cwd: PortablePath, name: Filename) {
|
||||
const path = ppath.join(cwd, name);
|
||||
|
||||
await xfs.writeFilePromise(path, ``);
|
||||
await xfs.chmodPromise(path, 0o755);
|
||||
}
|
||||
|
||||
describe(`EnableCommand`, () => {
|
||||
it(`should add the binaries in the folder found in the PATH`, async () => {
|
||||
await xfs.mktempPromise(async cwd => {
|
||||
await makeBin(cwd, `corepack` as Filename);
|
||||
|
||||
const PATH = process.env.PATH;
|
||||
try {
|
||||
process.env.PATH = `${npath.fromPortablePath(cwd)}${delimiter}${PATH}`;
|
||||
await expect(runCli(cwd, [`enable`])).resolves.toMatchObject({
|
||||
exitCode: 0,
|
||||
});
|
||||
} finally {
|
||||
process.env.PATH = PATH;
|
||||
}
|
||||
|
||||
const sortedEntries = xfs.readdirPromise(cwd).then(entries => {
|
||||
return entries.sort();
|
||||
});
|
||||
|
||||
const expectedEntries = [`corepack`];
|
||||
for (const packageManager of SupportedPackageManagerSet)
|
||||
for (const binName of engine.getBinariesFor(packageManager))
|
||||
expectedEntries.push(binName);
|
||||
|
||||
await expect(sortedEntries).resolves.toEqual(expectedEntries.sort());
|
||||
});
|
||||
});
|
||||
|
||||
it(`should add the binaries to the specified folder when using --install-directory`, async () => {
|
||||
await xfs.mktempPromise(async cwd => {
|
||||
await makeBin(cwd, `corepack` as Filename);
|
||||
|
||||
await expect(runCli(cwd, [`enable`, `--install-directory`, npath.fromPortablePath(cwd)])).resolves.toMatchObject({
|
||||
exitCode: 0,
|
||||
});
|
||||
|
||||
const sortedEntries = xfs.readdirPromise(cwd).then(entries => {
|
||||
return entries.sort();
|
||||
});
|
||||
|
||||
const expectedEntries = [`corepack`];
|
||||
for (const packageManager of SupportedPackageManagerSet)
|
||||
for (const binName of engine.getBinariesFor(packageManager))
|
||||
expectedEntries.push(binName);
|
||||
|
||||
await expect(sortedEntries).resolves.toEqual(expectedEntries.sort());
|
||||
});
|
||||
});
|
||||
|
||||
it(`should add binaries only for the requested package managers`, async () => {
|
||||
await xfs.mktempPromise(async cwd => {
|
||||
await makeBin(cwd, `corepack` as Filename);
|
||||
|
||||
const PATH = process.env.PATH;
|
||||
try {
|
||||
process.env.PATH = `${npath.fromPortablePath(cwd)}${delimiter}${PATH}`;
|
||||
await expect(runCli(cwd, [`enable`, `yarn`])).resolves.toMatchObject({
|
||||
exitCode: 0,
|
||||
});
|
||||
} finally {
|
||||
process.env.PATH = PATH;
|
||||
}
|
||||
|
||||
const sortedEntries = xfs.readdirPromise(cwd).then(entries => {
|
||||
return entries.sort();
|
||||
});
|
||||
|
||||
const expectedEntries = [`corepack`];
|
||||
for (const binName of engine.getBinariesFor(SupportedPackageManagers.Yarn))
|
||||
expectedEntries.push(binName);
|
||||
|
||||
await expect(sortedEntries).resolves.toEqual(expectedEntries.sort());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,15 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "node",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"lib": ["dom", "es2017", "esnext.asynciterable"],
|
||||
"module": "commonjs",
|
||||
"resolveJsonModule": true,
|
||||
"strict": true,
|
||||
"target": "es2017"
|
||||
}
|
||||
"compilerOptions": {
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "node",
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"lib": ["dom", "es2017", "esnext.asynciterable"],
|
||||
"module": "commonjs",
|
||||
"resolveJsonModule": true,
|
||||
"strict": true,
|
||||
"target": "es2017"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ module.exports = {
|
|||
options: {
|
||||
compilerOptions: {
|
||||
module: `es6`,
|
||||
noEmit: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
11
yarn.lock
11
yarn.lock
|
|
@ -1014,6 +1014,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/which@npm:^1.3.2":
|
||||
version: 1.3.2
|
||||
resolution: "@types/which@npm:1.3.2"
|
||||
checksum: ffb779f93f76c0f79c0c1d7f9f36f5c396a8b04b5214cd905a0c22a16555f41d689940aa642fb23fd040e648a5ae7e15e5dcc2fd7d6c44608f5c3dabec9e02e7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/yargs-parser@npm:*":
|
||||
version: 15.0.0
|
||||
resolution: "@types/yargs-parser@npm:15.0.0"
|
||||
|
|
@ -2212,6 +2219,7 @@ __metadata:
|
|||
"@types/node": ^13.9.2
|
||||
"@types/semver": ^7.1.0
|
||||
"@types/tar": ^4.0.3
|
||||
"@types/which": ^1.3.2
|
||||
"@typescript-eslint/eslint-plugin": ^2.0.0
|
||||
"@typescript-eslint/parser": ^4.2.0
|
||||
"@yarnpkg/eslint-config": ^0.1.0
|
||||
|
|
@ -2232,6 +2240,7 @@ __metadata:
|
|||
typescript: ^3.9.7
|
||||
webpack: next
|
||||
webpack-cli: ^3.3.11
|
||||
which: ^2.0.2
|
||||
bin:
|
||||
corepack: ./dist/corepack.js
|
||||
pnpm: ./dist/pnpm.js
|
||||
|
|
@ -7126,7 +7135,7 @@ typescript@^3.9.7:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"which@npm:^2.0.1":
|
||||
"which@npm:^2.0.1, which@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "which@npm:2.0.2"
|
||||
dependencies:
|
||||
|
|
|
|||
Loading…
Reference in New Issue