feat!: breaking config changes for v7 (#4253)

ref https://github.com/pnpm/pnpm/discussions/3536
This commit is contained in:
Zoltan Kochan
2022-01-20 12:34:14 +02:00
committed by GitHub
parent 14f60eb105
commit 5168591786
31 changed files with 90 additions and 297 deletions

View File

@@ -0,0 +1,10 @@
---
"@pnpm/build-modules": major
"@pnpm/config": major
"@pnpm/core": major
"@pnpm/headless": major
"@pnpm/hoist": major
"@pnpm/link-bins": major
---
`extendNodePath` removed.

View File

@@ -0,0 +1,5 @@
---
"pnpm": major
---
The root package is excluded by default, when running `pnpm -r exec|run|add` [#2769](https://github.com/pnpm/pnpm/issues/2769).

View File

@@ -0,0 +1,9 @@
---
"pnpm": major
---
Filtering by path is done by globs.
In pnpm v6, in order to pick packages under a certain directory, the following filter was used: `--filter=./apps`
In pnpm v7, a glob should be used: `--filter=./apps/**`

View File

@@ -0,0 +1,9 @@
---
"pnpm": major
---
The `NODE_PATH` env variable is not set in the command shims (the files in `node_modules/.bin`). This env variable was really long and frequently caused errors on Windows.
Also, the `extend-node-path` setting is removed.
Related PR: [#4253](https://github.com/pnpm/pnpm/pull/4253)

View File

@@ -0,0 +1,5 @@
---
"pnpm": major
---
Side effects cache is turned on by default. To turn it off, use `side-effects-cache=true`.

View File

@@ -0,0 +1,5 @@
---
"pnpm": major
---
The `npm_config_argv` env variable is not set for scripts [#4153](https://github.com/pnpm/pnpm/discussions/4153).

View File

@@ -20,7 +20,6 @@ export default async (
childConcurrency?: number
depsToBuild?: Set<string>
depsStateCache: DepsStateCache
extendNodePath?: boolean
extraBinPaths?: string[]
extraEnv?: Record<string, string>
lockfileDir: string
@@ -70,7 +69,6 @@ async function buildDependency (
depPath: string,
depGraph: DependenciesGraph,
opts: {
extendNodePath?: boolean
extraBinPaths?: string[]
extraEnv?: Record<string, string>
depsStateCache: DepsStateCache
@@ -192,7 +190,6 @@ export async function linkBinsOfDependencies (
depNode: DependenciesGraphNode,
depGraph: DependenciesGraph,
opts: {
extendNodePath?: boolean
optional: boolean
warn: (message: string) => void
}
@@ -230,11 +227,11 @@ export async function linkBinsOfDependencies (
}))
)
await linkBinsOfPackages(pkgs, binPath, { extendNodePath: opts.extendNodePath, warn: opts.warn })
await linkBinsOfPackages(pkgs, binPath)
// link also the bundled dependencies` bins
if (depNode.hasBundledDependencies) {
const bundledModules = path.join(depNode.dir, 'node_modules')
await linkBins(bundledModules, binPath, { extendNodePath: opts.extendNodePath, warn: opts.warn })
await linkBins(bundledModules, binPath, { warn: opts.warn })
}
}

View File

@@ -40,7 +40,6 @@
"@pnpm/types": "workspace:7.9.0",
"@zkochan/npm-conf": "2.0.2",
"camelcase": "^6.2.0",
"can-write-to-dir": "^1.1.1",
"is-subdir": "^1.1.1",
"normalize-registry-url": "2.0.0",
"ramda": "^0.27.1",

View File

@@ -145,7 +145,6 @@ export interface Config {
testPattern?: string[]
changedFilesIgnorePattern?: string[]
extendNodePath?: boolean
rootProjectManifest?: ProjectManifest
userConfig: Record<string, string>
}

View File

@@ -1,17 +0,0 @@
import path from 'path'
import isSubdir from 'is-subdir'
export default function findBestGlobalPrefixOnWindows (
defaultNpmGlobalPrefix: string,
env: { [key: string]: string | undefined }
) {
if (process.platform !== 'win32') return defaultNpmGlobalPrefix
if (
(env.LOCALAPPDATA != null && isSubdir(env.LOCALAPPDATA, defaultNpmGlobalPrefix)) ||
(env.APPDATA != null && isSubdir(env.APPDATA, defaultNpmGlobalPrefix))
) {
return defaultNpmGlobalPrefix
}
if (env.APPDATA) return path.join(env.APPDATA, 'npm')
return defaultNpmGlobalPrefix
}

View File

@@ -1,6 +1,5 @@
import path from 'path'
import fs from 'fs'
import os from 'os'
import { LAYOUT_VERSION } from '@pnpm/constants'
import PnpmError from '@pnpm/error'
import globalBinDir from '@pnpm/global-bin-dir'
@@ -9,13 +8,11 @@ import { safeReadProjectManifestOnly } from '@pnpm/read-project-manifest'
import camelcase from 'camelcase'
import loadNpmConf from '@zkochan/npm-conf'
import npmTypes from '@zkochan/npm-conf/lib/types'
import { sync as canWriteToDir } from 'can-write-to-dir'
import normalizeRegistryUrl from 'normalize-registry-url'
import fromPairs from 'ramda/src/fromPairs'
import realpathMissing from 'realpath-missing'
import whichcb from 'which'
import getScopeRegistries from './getScopeRegistries'
import findBestGlobalPrefix from './findBestGlobalPrefix'
import { getCacheDir, getConfigDir, getDataDir, getStateDir } from './dirs'
import {
Config,
@@ -28,8 +25,6 @@ export { Config, UniversalOptions }
const npmDefaults = loadNpmConf.defaults
const PNPM_GLOBAL = 'pnpm-global'
async function which (cmd: string) {
return new Promise<string>((resolve, reject) => {
whichcb(cmd, (err, resolvedPath) => (err != null) ? reject(err) : resolve(resolvedPath!))
@@ -46,7 +41,6 @@ export const types = Object.assign({
dir: String,
'enable-modules-dir': Boolean,
'enable-pre-post-scripts': Boolean,
'extend-node-path': Boolean,
'fetch-timeout': Number,
'fetching-concurrency': Number,
filter: [String, Array],
@@ -175,7 +169,6 @@ export default async (
bail: true,
color: 'auto',
'enable-modules-dir': true,
'extend-node-path': true,
'fetch-retries': 2,
'fetch-retry-factor': 10,
'fetch-retry-maxtimeout': 60000,
@@ -203,6 +196,7 @@ export default async (
'save-peer': false,
'save-workspace-protocol': true,
'scripts-prepend-node-path': false,
'side-effects-cache': true,
symlink: true,
'shared-workspace-lockfile': true,
'shared-workspace-shrinkwrap': true,
@@ -282,20 +276,8 @@ export default async (
let globalDirRoot
if (pnpmConfig['globalDir']) {
globalDirRoot = pnpmConfig['globalDir']
} else if (pnpmConfig.useBetaCli) {
globalDirRoot = path.join(pnpmConfig.pnpmHomeDir, 'global-packages')
} else {
let npmGlobalPrefix: string = findBestGlobalPrefix(npmConfig.globalPrefix, process.env)
const globalDirName = `${path.sep}${PNPM_GLOBAL}${path.sep}`
if (npmGlobalPrefix.includes(globalDirName)) {
npmGlobalPrefix = npmGlobalPrefix.substring(0, npmGlobalPrefix.indexOf(globalDirName))
} else {
const npmGlobalBinDir = process.platform === 'win32'
? npmGlobalPrefix
: path.resolve(npmGlobalPrefix, 'bin')
knownGlobalBinDirCandidates.push(npmGlobalBinDir)
}
globalDirRoot = path.join(firstWithWriteAccess([npmGlobalPrefix, os.homedir()]), PNPM_GLOBAL)
globalDirRoot = path.join(pnpmConfig.pnpmHomeDir, 'global-packages')
}
pnpmConfig.dir = path.join(globalDirRoot, LAYOUT_VERSION.toString())
@@ -318,7 +300,6 @@ export default async (
pnpmConfig.saveProd = true
pnpmConfig.saveDev = false
pnpmConfig.saveOptional = false
pnpmConfig.extendNodePath = false
if ((pnpmConfig.hoistPattern != null) && (pnpmConfig.hoistPattern.length > 1 || pnpmConfig.hoistPattern[0] !== '*')) {
if (opts.cliOptions['hoist-pattern']) {
throw new PnpmError('CONFIG_CONFLICT_HOIST_PATTERN_WITH_GLOBAL',
@@ -501,23 +482,3 @@ function getProcessEnv (env: string) {
process.env[env.toUpperCase()] ??
process.env[env.toLowerCase()]
}
function firstWithWriteAccess (dirs: string[]) {
const first = dirs.find((dir) => {
try {
return canWriteToDir(dir)
} catch (err: any) { // eslint-disable-line
if (err.code !== 'ENOENT') throw err
}
try {
fs.mkdirSync(dir, { recursive: true })
return true
} catch (err: any) { // eslint-disable-line
return false
}
})
if (first == null) {
throw new PnpmError('NO_SUITABLE_GLOBAL_DIR', `pnpm has no write access to global direcotry. Tried locations: ${dirs.join(', ')}`)
}
return first
}

View File

@@ -1,36 +0,0 @@
import findBestGlobalPrefix from '../lib/findBestGlobalPrefix'
test('findBestGlobalPrefix()', () => {
if (process.platform !== 'win32') {
// skipping on non-windows
return
}
const env = {
APPDATA: 'C:\\Users\\Imre\\AppData\\Roaming',
LOCALAPPDATA: 'C:\\Users\\Imre\\AppData\\Local',
}
expect(
// keep npm global prefix if is inside AppData\Local
findBestGlobalPrefix('C:\\Users\\Imre\\AppData\\Local\\nvs\\default', env)).toEqual(
'C:\\Users\\Imre\\AppData\\Local\\nvs\\default'
)
expect(
// keep npm global prefix if is inside AppData\Roaming
findBestGlobalPrefix('C:\\Users\\Imre\\AppData\\Roaming\\nvs\\default', env)).toEqual(
'C:\\Users\\Imre\\AppData\\Roaming\\nvs\\default'
)
expect(
// prefer location in AppData\Roaming
findBestGlobalPrefix('C:\\foo', env)).toEqual(
'C:\\Users\\Imre\\AppData\\Roaming\\npm'
)
expect(
findBestGlobalPrefix('C:\\foo', {})).toEqual(
'C:\\foo'
)
})

View File

@@ -62,7 +62,6 @@ test('correct settings on global install', async () => {
},
})
expect(config.save).toBe(true)
expect(config.extendNodePath).toBe(false)
})
test('throw error if --shared-workspace-lockfile is used with --global', async () => {
@@ -774,18 +773,3 @@ test('getConfig() sets sideEffectsCacheRead and sideEffectsCacheWrite when side-
expect(config.sideEffectsCacheRead).toBeTruthy()
expect(config.sideEffectsCacheWrite).toBeTruthy()
})
test('getConfig() sets sideEffectsCacheRead and sideEffectsCacheWrite when side-effects-cache-readonly is set', async () => {
const { config } = await getConfig({
cliOptions: {
'side-effects-cache-readonly': true,
},
packageManager: {
name: 'pnpm',
version: '1.0.0',
},
})
expect(config).toBeDefined()
expect(config.sideEffectsCacheRead).toBeTruthy()
expect(config.sideEffectsCacheWrite).toBeFalsy()
})

View File

@@ -19,7 +19,6 @@ export interface StrictInstallOptions {
frozenLockfile: boolean
frozenLockfileIfExists: boolean
enablePnp: boolean
extendNodePath: boolean
extraBinPaths: string[]
useLockfile: boolean
linkWorkspacePackagesDepth: number
@@ -108,7 +107,6 @@ const defaults = async (opts: InstallOptions) => {
depth: 0,
enablePnp: false,
engineStrict: false,
extendNodePath: true,
force: false,
forceSharedLockfile: false,
frozenLockfile: false,

View File

@@ -764,7 +764,6 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
dependenciesByProjectId,
depsStateCache,
force: opts.force,
extendNodePath: opts.extendNodePath,
hoistedDependencies: ctx.hoistedDependencies,
hoistedModulesDir: ctx.hoistedModulesDir,
hoistPattern: ctx.hoistPattern,
@@ -823,7 +822,6 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
childConcurrency: opts.childConcurrency,
depsStateCache,
depsToBuild: new Set(result.newDepPaths),
extendNodePath: opts.extendNodePath,
extraBinPaths: ctx.extraBinPaths,
extraEnv,
lockfileDir: ctx.lockfileDir,
@@ -861,7 +859,6 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
}, {})
linkedPackages = await linkBins(project.modulesDir, project.binsDir, {
allowExoticManifests: true,
extendNodePath: opts.extendNodePath,
projectManifest: project.manifest,
nodeExecPathByAlias,
warn: binWarn.bind(null, project.rootDir),
@@ -891,8 +888,7 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
)
)
.filter(({ manifest }) => manifest != null) as Array<{ location: string, manifest: DependencyManifest }>,
project.binsDir,
{ extendNodePath: opts.extendNodePath, warn: binWarn.bind(null, project.rootDir) }
project.binsDir
)
}
const projectToInstall = projects[index]

View File

@@ -48,7 +48,6 @@ export default async function linkPackages (
}
force: boolean
depsStateCache: DepsStateCache
extendNodePath?: boolean
hoistedDependencies: HoistedDependencies
hoistedModulesDir: string
hoistPattern?: string[]
@@ -249,7 +248,6 @@ export default async function linkPackages (
packages: omit(Array.from(opts.skipped), currentLockfile.packages),
}
newHoistedDependencies = await hoist({
extendNodePath: opts.extendNodePath,
lockfile: hoistLockfile,
importerIds: projectIds,
lockfileDir: opts.lockfileDir,

View File

@@ -144,10 +144,7 @@ export default async function link (
}
const linkToBin = maybeOpts?.linkToBin ?? path.join(destModules, '.bin')
await linkBinsOfPackages(linkedPkgs.map((p) => ({ manifest: p.manifest, location: p.path })), linkToBin, {
extendNodePath: opts.extendNodePath,
warn: (message: string) => logger.info({ message, prefix: opts.dir }),
})
await linkBinsOfPackages(linkedPkgs.map((p) => ({ manifest: p.manifest, location: p.path })), linkToBin)
let newPkg!: ProjectManifest
if (opts.targetDependenciesField) {

View File

@@ -22,7 +22,6 @@ interface StrictLinkOptions {
reporter: ReporterFunction
targetDependenciesField?: DependenciesField
dir: string
extendNodePath: boolean
hoistPattern: string[] | undefined
forceHoistPattern: boolean
@@ -54,7 +53,6 @@ async function defaults (opts: LinkOptions) {
return {
binsDir: path.join(dir, 'node_modules', '.bin'),
dir,
extendNodePath: true,
force: false,
forceSharedLockfile: false,
hoistPattern: undefined,

View File

@@ -558,27 +558,6 @@ test('bin specified in the directories property linked to .bin folder', async ()
await project.isExecutable('.bin/pkg-with-directories-bin')
})
test('command shim is created withoud NODE_PATH', async () => {
const project = prepareEmpty()
const manifest = await addDependenciesToPackage({}, ['rimraf@2.5.1'], await testDefaults({ fastUnpack: false, extendNodePath: false }))
{
await project.isExecutable('.bin/rimraf')
const cmdContent = await fs.readFile('node_modules/.bin/rimraf')
expect(cmdContent).not.toContain('NODE_PATH')
}
await rimraf('node_modules')
await install(manifest, await testDefaults({ extendNodePath: true, fastUnpack: false, frozenLockfile: true }))
{
await project.isExecutable('.bin/rimraf')
const cmdContent = await fs.readFile('node_modules/.bin/rimraf')
expect(cmdContent).not.toContain('NODE_PATH')
}
})
testOnNonWindows('building native addons', async () => {
const project = prepareEmpty()

View File

@@ -94,7 +94,6 @@ export interface HeadlessOptions {
}
enablePnp?: boolean
engineStrict: boolean
extendNodePath?: boolean
extraBinPaths?: string[]
ignoreScripts: boolean
ignorePackageManifest?: boolean
@@ -288,7 +287,6 @@ export default async (opts: HeadlessOptions) => {
if (opts.nodeLinker === 'hoisted' && hierarchy && prevGraph) {
await linkHoistedModules(opts.storeController, graph, prevGraph, hierarchy, {
depsStateCache,
extendNodePath: opts.extendNodePath,
force: opts.force,
lockfileDir: opts.lockfileDir,
sideEffectsCacheRead: opts.sideEffectsCacheRead,
@@ -338,7 +336,6 @@ export default async (opts: HeadlessOptions) => {
packages: omit(Array.from(skipped), filteredLockfile.packages),
}
newHoistedDependencies = await hoist({
extendNodePath: opts.extendNodePath,
lockfile: hoistLockfile,
importerIds,
lockfileDir,
@@ -352,7 +349,7 @@ export default async (opts: HeadlessOptions) => {
newHoistedDependencies = {}
}
await linkAllBins(graph, { extendNodePath: opts.extendNodePath, optional: opts.include.optionalDependencies, warn })
await linkAllBins(graph, { optional: opts.include.optionalDependencies, warn })
if ((currentLockfile != null) && !equals(importerIds.sort(), Object.keys(filteredLockfile.importers).sort())) {
Object.assign(filteredLockfile.packages, currentLockfile.packages)
@@ -410,7 +407,6 @@ export default async (opts: HeadlessOptions) => {
await buildModules(graph, Array.from(directNodes), {
childConcurrency: opts.childConcurrency,
extraBinPaths,
extendNodePath: opts.extendNodePath,
extraEnv,
depsStateCache,
lockfileDir,
@@ -432,7 +428,7 @@ export default async (opts: HeadlessOptions) => {
if (!opts.ignorePackageManifest) {
await Promise.all(opts.projects.map(async (project) => {
if (opts.publicHoistPattern?.length && path.relative(opts.lockfileDir, project.rootDir) === '') {
await linkBinsOfImporter(project, { extendNodePath: opts.extendNodePath })
await linkBinsOfImporter(project)
} else {
const directPkgDirs = Object.values(directDependenciesByImporterId[project.id])
await linkBinsOfPackages(
@@ -445,11 +441,7 @@ export default async (opts: HeadlessOptions) => {
)
)
.filter(({ manifest }) => manifest != null) as Array<{ location: string, manifest: DependencyManifest }>,
project.binsDir,
{
extendNodePath: opts.extendNodePath,
warn: (message: string) => logger.info({ message, prefix: project.rootDir }),
}
project.binsDir
)
}
}))
@@ -542,15 +534,11 @@ async function linkBinsOfImporter (
manifest: ProjectManifest
modulesDir: string
rootDir: string
},
opts: {
extendNodePath?: boolean
}
) {
const warn = (message: string) => logger.info({ message, prefix: rootDir })
return linkBins(modulesDir, binsDir, {
allowExoticManifests: true,
extendNodePath: opts.extendNodePath,
projectManifest: manifest,
warn,
})
@@ -687,7 +675,6 @@ async function linkAllPkgs (
async function linkAllBins (
depGraph: DependenciesGraph,
opts: {
extendNodePath?: boolean
optional: boolean
warn: (message: string) => void
}
@@ -709,7 +696,7 @@ async function linkAllBins (
const pkgSnapshots = props<string, DependenciesGraphNode>(Object.values(childrenToLink), depGraph)
if (pkgSnapshots.includes(undefined as any)) { // eslint-disable-line
await linkBins(depNode.modules, binPath, { extendNodePath: opts.extendNodePath, warn: opts.warn })
await linkBins(depNode.modules, binPath, { warn: opts.warn })
} else {
const pkgs = await Promise.all(
pkgSnapshots
@@ -720,13 +707,13 @@ async function linkAllBins (
}))
)
await linkBinsOfPackages(pkgs, binPath, { extendNodePath: opts.extendNodePath, warn: opts.warn })
await linkBinsOfPackages(pkgs, binPath)
}
// link also the bundled dependencies` bins
if (depNode.hasBundledDependencies) {
const bundledModules = path.join(depNode.dir, 'node_modules')
await linkBins(bundledModules, binPath, { extendNodePath: opts.extendNodePath, warn: opts.warn })
await linkBins(bundledModules, binPath, { warn: opts.warn })
}
}))
)

View File

@@ -26,7 +26,6 @@ export default async function linkHoistedModules (
hierarchy: DepHierarchy,
opts: {
depsStateCache: DepsStateCache
extendNodePath?: boolean
force: boolean
lockfileDir: string
sideEffectsCacheRead: boolean
@@ -82,7 +81,6 @@ async function linkAllPkgsInOrder (
parentDir: string,
opts: {
depsStateCache: DepsStateCache
extendNodePath?: boolean
force: boolean
lockfileDir: string
sideEffectsCacheRead: boolean
@@ -125,7 +123,6 @@ async function linkAllPkgsInOrder (
const binsDir = path.join(modulesDir, '.bin')
await linkBins(modulesDir, binsDir, {
allowExoticManifests: true,
extendNodePath: opts.extendNodePath,
warn: opts.warn,
})
}

View File

@@ -16,7 +16,6 @@ const hoistLogger = logger('hoist')
export default async function hoistByLockfile (
opts: {
extendNodePath?: boolean
lockfile: Lockfile
lockfileDir: string
importerIds?: string[]
@@ -67,7 +66,7 @@ export default async function hoistByLockfile (
// the bins of the project's direct dependencies.
// This is possible because the publicly hoisted modules
// are in the same directory as the regular dependencies.
await linkAllBins(opts.privateHoistedModulesDir, { extendNodePath: opts.extendNodePath })
await linkAllBins(opts.privateHoistedModulesDir)
return hoistedDependencies
}
@@ -87,14 +86,14 @@ function createGetAliasHoistType (
}
}
async function linkAllBins (modulesDir: string, opts: { extendNodePath?: boolean }) {
async function linkAllBins (modulesDir: string) {
const bin = path.join(modulesDir, '.bin')
const warn: WarnFunction = (message, code) => {
if (code === 'BINARIES_CONFLICT') return
logger.info({ message, prefix: path.join(modulesDir, '../..') })
}
try {
await linkBins(modulesDir, bin, { allowExoticManifests: true, extendNodePath: opts.extendNodePath, warn })
await linkBins(modulesDir, bin, { allowExoticManifests: true, warn })
} catch (err: any) { // eslint-disable-line
// Some packages generate their commands with lifecycle hooks.
// At this stage, such commands are not generated yet.

View File

@@ -1,5 +1,4 @@
import { promises as fs } from 'fs'
import Module from 'module'
import path from 'path'
import PnpmError from '@pnpm/error'
import logger, { globalWarn } from '@pnpm/logger'
@@ -17,7 +16,6 @@ import pSettle from 'p-settle'
import { KeyValuePair } from 'ramda'
import fromPairs from 'ramda/src/fromPairs'
import isEmpty from 'ramda/src/isEmpty'
import union from 'ramda/src/union'
import unnest from 'ramda/src/unnest'
import partition from 'ramda/src/partition'
import fixBin from 'bin-links/lib/fix-bin'
@@ -36,7 +34,6 @@ export default async (
binsDir: string,
opts: {
allowExoticManifests?: boolean
extendNodePath?: boolean
nodeExecPathByAlias?: Record<string, string>
projectManifest?: ProjectManifest
warn: WarnFunction
@@ -71,7 +68,7 @@ export default async (
)
const cmdsToLink = directDependencies != null ? preferDirectCmds(allCmds) : allCmds
return linkBins(cmdsToLink, binsDir, opts)
return linkBins(cmdsToLink, binsDir)
}
function preferDirectCmds (allCmds: Array<CommandInfo & { isDirectDependency?: boolean }>) {
@@ -89,11 +86,7 @@ export async function linkBinsOfPackages (
nodeExecPath?: string
location: string
}>,
binsTarget: string,
opts: {
extendNodePath?: boolean
warn: WarnFunction
}
binsTarget: string
): Promise<string[]> {
if (pkgs.length === 0) return []
@@ -105,7 +98,7 @@ export async function linkBinsOfPackages (
.filter((cmds: Command[]) => cmds.length)
)
return linkBins(allCmds, binsTarget, opts)
return linkBins(allCmds, binsTarget)
}
type CommandInfo = Command & {
@@ -117,10 +110,7 @@ type CommandInfo = Command & {
async function linkBins (
allCmds: CommandInfo[],
binsDir: string,
opts: {
extendNodePath?: boolean
}
binsDir: string
): Promise<string[]> {
if (allCmds.length === 0) return [] as string[]
@@ -128,7 +118,7 @@ async function linkBins (
const [cmdsWithOwnName, cmdsWithOtherNames] = partition(({ ownName }) => ownName, allCmds)
const results1 = await pSettle(cmdsWithOwnName.map(async (cmd) => linkBin(cmd, binsDir, opts)))
const results1 = await pSettle(cmdsWithOwnName.map(async (cmd) => linkBin(cmd, binsDir)))
const usedNames = fromPairs(cmdsWithOwnName.map((cmd) => [cmd.name, cmd.name] as KeyValuePair<string, string>))
const results2 = await pSettle(cmdsWithOtherNames.map(async (cmd) => {
@@ -142,7 +132,7 @@ async function linkBins (
return Promise.resolve(undefined)
}
usedNames[cmd.name] = cmd.pkgName
return linkBin(cmd, binsDir, opts)
return linkBin(cmd, binsDir)
}))
// We want to create all commands that we can create before throwing an exception
@@ -200,21 +190,12 @@ async function getPackageBinsFromManifest (manifest: DependencyManifest, pkgDir:
}))
}
async function linkBin (cmd: CommandInfo, binsDir: string, opts?: { extendNodePath?: boolean }) {
async function linkBin (cmd: CommandInfo, binsDir: string) {
const externalBinPath = path.join(binsDir, cmd.name)
try {
let nodePath: string[] | undefined
if (opts?.extendNodePath !== false) {
nodePath = await getBinNodePaths(cmd.path)
const binsParentDir = path.dirname(binsDir)
if (path.relative(cmd.path, binsParentDir) !== '') {
nodePath = union(nodePath, await getBinNodePaths(binsParentDir))
}
}
await cmdShim(cmd.path, externalBinPath, {
createPwshFile: cmd.makePowerShellShim,
nodePath,
nodeExecPath: cmd.nodeExecPath,
})
} catch (err: any) { // eslint-disable-line
@@ -231,16 +212,6 @@ async function linkBin (cmd: CommandInfo, binsDir: string, opts?: { extendNodePa
}
}
async function getBinNodePaths (target: string): Promise<string[]> {
const targetDir = path.dirname(target)
const targetRealPath = await fs.realpath(targetDir)
return union(
Module['_nodeModulePaths'](targetRealPath),
Module['_nodeModulePaths'](targetDir)
)
}
async function safeReadPkgJson (pkgDir: string): Promise<DependencyManifest | null> {
try {
return await readPackageJsonFromDir(pkgDir) as DependencyManifest

View File

@@ -146,7 +146,6 @@ test('linkBins() does not link own bins', async () => {
test('linkBinsOfPackages()', async () => {
const binTarget = tempy.directory()
const simpleFixture = f.prepare('simple-fixture')
const warn = jest.fn()
await linkBinsOfPackages(
[
@@ -155,11 +154,9 @@ test('linkBinsOfPackages()', async () => {
manifest: (await import(path.join(simpleFixture, 'node_modules/simple/package.json'))).default,
},
],
binTarget,
{ warn }
binTarget
)
expect(warn).not.toHaveBeenCalled()
expect(await fs.readdir(binTarget)).toEqual(getExpectedBins(['simple']))
const binLocation = path.join(binTarget, 'simple')
expect(await exists(binLocation)).toBe(true)
@@ -200,7 +197,6 @@ test('linkBins() resolves conflicts. Prefer packages that use their name as bin
test('linkBinsOfPackages() resolves conflicts. Prefer packages that use their name as bin name', async () => {
const binTarget = tempy.directory()
const binNameConflictsFixture = f.prepare('bin-name-conflicts')
const warn = jest.fn()
const modulesPath = path.join(binNameConflictsFixture, 'node_modules')
@@ -215,8 +211,7 @@ test('linkBinsOfPackages() resolves conflicts. Prefer packages that use their na
manifest: (await import(path.join(modulesPath, 'foo', 'package.json'))).default,
},
],
binTarget,
{ warn }
binTarget
)
expect(binsConflictLogger.debug).toHaveBeenCalledWith({

View File

@@ -108,10 +108,6 @@ export default async function run (inputArgv: string[]) {
process.exitCode = 1
return
}
if (!config.useBetaCli) {
process.env['npm_config_argv'] = JSON.stringify(argv)
config.rawConfig.argv = process.env['npm_config_argv']
}
let write: (text: string) => void = process.stdout.write.bind(process.stdout)
// chalk reads the FORCE_COLOR env variable
@@ -194,7 +190,7 @@ export default async function run (inputArgv: string[]) {
const relativeWSDirPath = () => path.relative(process.cwd(), wsDir) || '.'
if (config.workspaceRoot) {
filters.push({ filter: `{${relativeWSDirPath()}}`, followProdDepsOnly: false })
} else if (config.useBetaCli && (cmd === 'run' || cmd === 'exec' || cmd === 'add' || cmd === 'test')) {
} else if (cmd === 'run' || cmd === 'exec' || cmd === 'add' || cmd === 'test') {
filters.push({ filter: `!{${relativeWSDirPath()}}`, followProdDepsOnly: false })
}
@@ -204,7 +200,7 @@ export default async function run (inputArgv: string[]) {
workspaceDir: wsDir,
testPattern: config.testPattern,
changedFilesIgnorePattern: config.changedFilesIgnorePattern,
useGlobDirFiltering: config.useBetaCli,
useGlobDirFiltering: true,
})
config.selectedProjectsGraph = filterResults.selectedProjectsGraph
if (isEmpty(config.selectedProjectsGraph)) {

View File

@@ -14,8 +14,7 @@ test('global installation', async () => {
const global = path.resolve('..', 'global')
await fs.mkdir(global)
const env = { NPM_CONFIG_PREFIX: global }
if (process.env.APPDATA) env['APPDATA'] = global
const env = { XDG_DATA_HOME: global }
await execPnpm(['install', '--global', 'is-positive'], { env })
@@ -23,7 +22,7 @@ test('global installation', async () => {
// https://github.com/pnpm/pnpm/issues/808
await execPnpm(['install', '--global', 'is-negative'], { env })
const globalPrefix = path.join(global, `pnpm-global/${LAYOUT_VERSION}`)
const globalPrefix = path.join(global, `pnpm/global-packages/${LAYOUT_VERSION}`)
const { default: isPositive } = await import(path.join(globalPrefix, 'node_modules', 'is-positive'))
expect(typeof isPositive).toBe('function')
@@ -48,14 +47,12 @@ test('always install latest when doing global installation without spec', async
const global = path.resolve('..', 'global')
await fs.mkdir(global)
const env = { NPM_CONFIG_PREFIX: global }
if (process.env.APPDATA) env['APPDATA'] = global
const env = { XDG_DATA_HOME: global }
await execPnpm(['install', '-g', 'peer-c@1'], { env })
await execPnpm(['install', '-g', 'peer-c'], { env })
const globalPrefix = path.join(global, `pnpm-global/${LAYOUT_VERSION}`)
const globalPrefix = path.join(global, `pnpm/global-packages/${LAYOUT_VERSION}`)
process.chdir(globalPrefix)
@@ -73,10 +70,9 @@ test('run lifecycle events of global packages in correct working directory', asy
const global = path.resolve('..', 'global')
await fs.mkdir(global)
const env = { NPM_CONFIG_PREFIX: global }
if (process.env.APPDATA) env['APPDATA'] = global
const env = { XDG_DATA_HOME: global }
await execPnpm(['install', '-g', 'postinstall-calls-pnpm@1.0.0'], { env })
expect(await exists(path.join(global, `pnpm-global/${LAYOUT_VERSION}/node_modules/postinstall-calls-pnpm/created-by-postinstall`))).toBeTruthy()
expect(await exists(path.join(global, `pnpm/global-packages/${LAYOUT_VERSION}/node_modules/postinstall-calls-pnpm/created-by-postinstall`))).toBeTruthy()
})

View File

@@ -1,4 +1,3 @@
import { promises as fs } from 'fs'
import path from 'path'
import prepare from '@pnpm/prepare'
import { PackageManifest } from '@pnpm/types'
@@ -100,46 +99,6 @@ test('prepare is executed after argumentless installation', () => {
expect(result.stdout.toString()).toContain('Hello world!')
})
test('lifecycle events don\'t have when config is set', async () => {
prepare({
dependencies: {
'write-lifecycle-env': '^1.0.0',
},
scripts: {
postinstall: 'write-lifecycle-env',
},
})
await fs.writeFile('.npmrc', 'use-beta-cli=true', 'utf8')
execPnpmSync(['install'])
const lifecycleEnv = await loadJsonFile<object>('env.json')
expect(lifecycleEnv['npm_config_argv']).toStrictEqual(undefined)
})
test('lifecycle events have proper npm_config_argv', async () => {
prepare({
dependencies: {
'write-lifecycle-env': '^1.0.0',
},
scripts: {
postinstall: 'write-lifecycle-env',
},
})
await fs.writeFile('.npmrc', 'use-beta-cli=false', 'utf8')
execPnpmSync(['install'])
const lifecycleEnv = await loadJsonFile<object>('env.json')
expect(JSON.parse(lifecycleEnv['npm_config_argv'])).toStrictEqual({
cooked: ['install'],
original: ['install'],
remain: ['install'],
})
})
test('dependency should not be added to package.json and lockfile if it was not built successfully', async () => {
const project = prepare({ name: 'foo', version: '1.0.0' })

View File

@@ -1,4 +1,4 @@
import { promises as fs } from 'fs'
import { promises as fs, writeFileSync } from 'fs'
import path from 'path'
import { WANTED_LOCKFILE } from '@pnpm/constants'
import { Lockfile } from '@pnpm/lockfile-types'
@@ -80,7 +80,7 @@ test('write to stderr when --use-stderr is used', async () => {
test('install with package-lock=false in .npmrc', async () => {
const project = prepare()
await fs.writeFile('.npmrc', 'package-lock=false', 'utf8')
writeFileSync('.npmrc', 'package-lock=false', 'utf8')
await execPnpm(['add', 'is-positive'])
@@ -238,10 +238,17 @@ test('`pnpm add` should fail if no package name was provided', () => {
expect(stdout.toString()).toContain('`pnpm add` requires the package name')
})
test('`pnpm recursive add` should fail if no package name was provided', () => {
prepare()
test('`pnpm -r add` should fail if no package name was provided', () => {
preparePackages([
{
name: 'project',
version: '1.0.0',
},
])
const { status, stdout } = execPnpmSync(['recursive', 'add'])
writeFileSync('pnpm-workspace.yaml', '', 'utf8')
const { status, stdout } = execPnpmSync(['-r', 'add'])
expect(status).toBe(1)
expect(stdout.toString()).toContain('`pnpm add` requires the package name')

View File

@@ -24,8 +24,7 @@ skipOnWindows('self-update stops the store server', async () => {
const global = path.resolve('global')
await fs.mkdir(global)
const env = { NPM_CONFIG_PREFIX: global }
if (process.env.APPDATA) env['APPDATA'] = global
const env = { XDG_DATA_HOME: global }
await execPnpm(['install', '-g', 'pnpm', '--store-dir', path.resolve('..', 'store')], { env })

View File

@@ -2,7 +2,6 @@ import { promises as fs } from 'fs'
import path from 'path'
import { LAYOUT_VERSION } from '@pnpm/constants'
import { tempDir } from '@pnpm/prepare'
import isWindows from 'is-windows'
import { execPnpmSync } from './utils'
test('pnpm root', async () => {
@@ -22,16 +21,10 @@ test('pnpm root -g', async () => {
const global = path.resolve('global')
await fs.mkdir(global)
const env = { NPM_CONFIG_PREFIX: global }
if (process.env.APPDATA) env['APPDATA'] = global
const env = { XDG_DATA_HOME: global }
const result = execPnpmSync(['root', '-g'], { env })
expect(result.status).toBe(0)
if (isWindows()) {
expect(result.stdout.toString()).toBe(path.join(global, `pnpm-global/${LAYOUT_VERSION}/node_modules`) + '\n')
} else {
expect(result.stdout.toString()).toBe(path.join(global, `pnpm-global/${LAYOUT_VERSION}/node_modules`) + '\n')
}
expect(result.stdout.toString()).toBe(path.join(global, `pnpm/global-packages/${LAYOUT_VERSION}/node_modules`) + '\n')
})

2
pnpm-lock.yaml generated
View File

@@ -350,7 +350,6 @@ importers:
'@types/which': ^2.0.0
'@zkochan/npm-conf': 2.0.2
camelcase: ^6.2.0
can-write-to-dir: ^1.1.1
is-subdir: ^1.1.1
normalize-registry-url: 2.0.0
ramda: ^0.27.1
@@ -366,7 +365,6 @@ importers:
'@pnpm/types': link:../types
'@zkochan/npm-conf': 2.0.2
camelcase: 6.3.0
can-write-to-dir: 1.1.1
is-subdir: 1.2.0
normalize-registry-url: 2.0.0
ramda: 0.27.2