feat!: remove independent-leaves=true support

PR #2571
This commit is contained in:
Zoltan Kochan
2020-05-22 11:09:05 +03:00
committed by GitHub
parent 4f5801b1c0
commit 802d145fcd
59 changed files with 53 additions and 722 deletions

View File

@@ -0,0 +1,18 @@
---
"@pnpm/config": major
"@pnpm/get-context": major
"@pnpm/headless": major
"@pnpm/hoist": major
"@pnpm/modules-yaml": major
"@pnpm/plugin-commands-installation": major
"@pnpm/plugin-commands-listing": major
"@pnpm/plugin-commands-outdated": major
"@pnpm/plugin-commands-rebuild": major
"@pnpm/plugin-commands-store": major
"pnpm": major
"@pnpm/read-projects-context": major
"@pnpm/resolve-dependencies": major
"supi": minor
---
Remove `independent-leaves` support.

View File

@@ -0,0 +1,8 @@
---
"@pnpm/package-requester": major
"@pnpm/package-store": major
"@pnpm/server": major
"@pnpm/store-controller-types": major
---
`getPackageLocation()` removed from store. Remove `inStoreLocation` from the result of `fetchPackage()`.

View File

@@ -24,6 +24,9 @@
{
"path": "../types"
},
{
"path": "../constants"
},
{
"path": "../lockfile-file"
}

View File

@@ -96,7 +96,6 @@ export interface Config {
repeatInstallDepth?: number,
ignorePnpmfile?: boolean,
pnpmfile: string,
independentLeaves?: boolean,
packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone',
hoistPattern?: string[],
useStoreServer?: boolean,

View File

@@ -44,7 +44,6 @@ export const types = Object.assign({
'hoist-pattern': Array,
'ignore-pnpmfile': Boolean,
'ignore-workspace-root-check': Boolean,
'independent-leaves': Boolean,
'link-workspace-packages': [Boolean, 'deep'],
'lockfile': Boolean,
'lockfile-dir': String,
@@ -230,19 +229,11 @@ export default async (
pnpmConfig.saveProd = true
pnpmConfig.saveDev = false
pnpmConfig.saveOptional = false
if (pnpmConfig.independentLeaves) {
if (opts.cliOptions['independent-leaves']) {
throw new PnpmError('CONFIG_CONFLICT_INDEPENDENT_LEAVES_WITH_GLOBAL',
'Configuration conflict. "independent-leaves" may not be used with "global"')
}
pnpmConfig.independentLeaves = false
}
if (pnpmConfig.hoistPattern && (pnpmConfig.hoistPattern.length > 1 || pnpmConfig.hoistPattern[0] !== '*')) {
if (opts.cliOptions['hoist-pattern']) {
throw new PnpmError('CONFIG_CONFLICT_HOIST_PATTERN_WITH_GLOBAL',
'Configuration conflict. "hoist-pattern" may not be used with "global"')
}
pnpmConfig.independentLeaves = false
}
if (pnpmConfig.linkWorkspacePackages) {
if (opts.cliOptions['link-workspace-packages']) {
@@ -320,9 +311,6 @@ export default async (
}
if (pnpmConfig['hoist'] === false) {
delete pnpmConfig.hoistPattern
} else if (pnpmConfig.independentLeaves === true) {
throw new PnpmError('CONFIG_CONFLICT_INDEPENDENT_LEAVES_AND_HOIST',
'"independent-leaves=true" can only be used when hoisting is off, so "hoist=false"')
}
if (typeof pnpmConfig['color'] === 'boolean') {
switch (pnpmConfig['color']) {

View File

@@ -11,7 +11,6 @@ import './findBestGlobalPrefixOnWindows'
// To override any local settings,
// we force the default values of config
delete process.env['npm_config_depth']
process.env['npm_config_independent_leaves'] = 'false'
process.env['npm_config_hoist'] = 'true'
delete process.env['npm_config_registry']
delete process.env['npm_config_virtual_store_dir']
@@ -90,25 +89,6 @@ test('throw error if --lockfile-dir is used with --global', async (t) => {
}
})
test('throw error if --independent-leaves is used with --global', async (t) => {
try {
await getConfig({
cliOptions: {
'global': true,
'independent-leaves': true,
},
packageManager: {
name: 'pnpm',
version: '1.0.0',
},
})
} catch (err) {
t.equal(err.message, 'Configuration conflict. "independent-leaves" may not be used with "global"')
t.equal((err as PnpmError).code, 'ERR_PNPM_CONFIG_CONFLICT_INDEPENDENT_LEAVES_WITH_GLOBAL')
t.end()
}
})
test('throw error if --hoist-pattern is used with --global', async (t) => {
try {
await getConfig({
@@ -442,47 +422,13 @@ test('throw error if --no-hoist is used with --hoist-pattern', async (t) => {
}
})
test('throw error if --independent-leaves is used without --no-hoist', async (t) => {
try {
await getConfig({
cliOptions: {
'independent-leaves': true,
},
packageManager: {
name: 'pnpm',
version: '1.0.0',
},
})
} catch (err) {
t.equal(err.message, '"independent-leaves=true" can only be used when hoisting is off, so "hoist=false"')
t.equal((err as PnpmError).code, 'ERR_PNPM_CONFIG_CONFLICT_INDEPENDENT_LEAVES_AND_HOIST')
t.end()
}
})
test('do not throw error if --independent-leaves is used with --no-hoist', async (t) => {
const { config } = await getConfig({
cliOptions: {
'hoist': false,
'independent-leaves': true,
},
packageManager: {
name: 'pnpm',
version: '1.0.0',
},
})
t.ok(config.independentLeaves)
t.notOk(config.hoistPattern)
t.end()
})
test('rawLocalConfig in a workspace', async (t) => {
const tmp = tempy.directory()
t.comment(`temp dir created: ${tmp}`)
process.chdir(tmp)
const workspaceDir = process.cwd()
await fs.writeFile('.npmrc', 'independent-leaves=true\nhoist-pattern=*', 'utf8')
await fs.writeFile('.npmrc', 'hoist-pattern=*', 'utf8')
await fs.mkdir('package')
process.chdir('package')
await fs.writeFile('.npmrc', 'hoist-pattern=eslint-*', 'utf8')
@@ -501,7 +447,6 @@ test('rawLocalConfig in a workspace', async (t) => {
t.deepEqual(config.rawLocalConfig, {
'hoist-pattern': 'eslint-*',
'independent-leaves': true,
'save-exact': true,
})
}
@@ -523,7 +468,6 @@ test('rawLocalConfig in a workspace', async (t) => {
t.deepEqual(config.rawLocalConfig, {
'hoist-pattern': '*',
'independent-leaves': true,
'save-exact': true,
})
}
@@ -535,7 +479,7 @@ test('rawLocalConfig', async (t) => {
t.comment(`temp dir created: ${tmp}`)
process.chdir(tmp)
await fs.writeFile('.npmrc', 'independent-leaves=true', 'utf8')
await fs.writeFile('.npmrc', 'modules-dir=modules', 'utf8')
const { config } = await getConfig({
cliOptions: {
@@ -548,7 +492,7 @@ test('rawLocalConfig', async (t) => {
})
t.deepEqual(config.rawLocalConfig, {
'independent-leaves': true,
'modules-dir': 'modules',
'save-exact': true,
})
t.end()

View File

@@ -1,4 +1,3 @@
independentLeaves: false
layoutVersion: 1
packageManager: pnpm@1.4.0
skipped: []

View File

@@ -6,7 +6,6 @@ included:
dependencies: true
devDependencies: true
optionalDependencies: true
independentLeaves: true
layoutVersion: 1
packageManager: pnpm@2.25.5
pendingBuilds: []

View File

@@ -28,7 +28,6 @@ export interface PnpmContext<T> {
extraBinPaths: string[],
hoistedAliases: {[depPath: string]: string[]}
include: IncludedDependencies,
independentLeaves: boolean,
modulesFile: Modules | null,
pendingBuilds: string[],
projects: Array<{
@@ -72,9 +71,6 @@ export default async function getContext<T> (
useLockfile: boolean,
virtualStoreDir?: string,
independentLeaves?: boolean,
forceIndependentLeaves?: boolean,
hoistPattern?: string[] | undefined,
forceHoistPattern?: boolean,
@@ -97,9 +93,6 @@ export default async function getContext<T> (
storeDir: opts.storeDir,
virtualStoreDir,
forceIndependentLeaves: opts.forceIndependentLeaves,
independentLeaves: opts.independentLeaves,
forceHoistPattern: opts.forceHoistPattern,
hoistPattern: opts.hoistPattern,
@@ -144,7 +137,6 @@ export default async function getContext<T> (
hoistedModulesDir,
hoistPattern: opts.hoistPattern,
include: opts.include || importersContext.include,
independentLeaves: Boolean(typeof importersContext.independentLeaves === 'undefined' ? opts.independentLeaves : importersContext.independentLeaves),
lockfileDir: opts.lockfileDir,
modulesFile: importersContext.modules,
pendingBuilds: importersContext.pendingBuilds,
@@ -189,9 +181,6 @@ async function validateModules (
storeDir: string,
virtualStoreDir: string,
independentLeaves?: boolean,
forceIndependentLeaves?: boolean,
hoistPattern?: string[] | undefined,
forceHoistPattern?: boolean,
@@ -218,30 +207,6 @@ async function validateModules (
+ ' You must remove that option, or else "pnpm install" to recreate the modules directory.'
)
}
if (opts.forceIndependentLeaves && Boolean(modules.independentLeaves) !== opts.independentLeaves) {
if (opts.forceNewModules) {
await Promise.all(projects.map(purgeModulesDirsOfImporter))
if (!rootProject) {
await purgeModulesDirsOfImporter({
modulesDir: path.join(opts.lockfileDir, opts.modulesDir),
rootDir: opts.lockfileDir,
})
}
return { purged: true }
}
if (modules.independentLeaves) {
throw new PnpmError(
'INDEPENDENT_LEAVES_WANTED',
'This modules directory was created using the --independent-leaves option.'
+ ' You must add that option, or else run "pnpm install" to recreate the modules directory.'
)
}
throw new PnpmError(
'INDEPENDENT_LEAVES_NOT_WANTED',
'This modules directory was created without the --independent-leaves option.'
+ ' You must remove that option, or else "pnpm install" to recreate the modules directory.'
)
}
let purged = false
if (opts.forceHoistPattern && rootProject) {
try {
@@ -338,7 +303,6 @@ export interface PnpmSingleContext {
importerId: string,
prefix: string,
include: IncludedDependencies,
independentLeaves: boolean,
modulesFile: Modules | null,
pendingBuilds: string[],
registries: Registries,
@@ -375,9 +339,6 @@ export async function getContextForSingleImporter (
shamefullyHoist?: boolean,
forceShamefullyHoist?: boolean,
independentLeaves?: boolean,
forceIndependentLeaves?: boolean,
},
alreadyPurged: boolean = false
): Promise<PnpmSingleContext> {
@@ -386,7 +347,6 @@ export async function getContextForSingleImporter (
hoistedAliases,
projects,
include,
independentLeaves,
modules,
pendingBuilds,
registries,
@@ -426,9 +386,6 @@ export async function getContextForSingleImporter (
forceHoistPattern: opts.forceHoistPattern,
hoistPattern: opts.hoistPattern,
forceIndependentLeaves: opts.forceIndependentLeaves,
independentLeaves: opts.independentLeaves,
forceShamefullyHoist: opts.forceShamefullyHoist,
shamefullyHoist: opts.shamefullyHoist,
})
@@ -454,7 +411,6 @@ export async function getContextForSingleImporter (
hoistPattern: opts.hoistPattern,
importerId,
include: opts.include || include,
independentLeaves: Boolean(typeof independentLeaves === 'undefined' ? opts.independentLeaves : independentLeaves),
lockfileDir: opts.lockfileDir,
manifest: opts.hooks?.readPackage?.(manifest) ?? manifest,
modulesDir,

View File

@@ -30,7 +30,6 @@ import {
import {
nameVerFromPkgSnapshot,
packageIdFromSnapshot,
packageIsIndependent,
pkgSnapshotToResolution,
satisfiesPackageManifest,
} from '@pnpm/lockfile-utils'
@@ -76,7 +75,6 @@ export interface HeadlessOptions {
extraBinPaths?: string[],
ignoreScripts: boolean,
include: IncludedDependencies,
independentLeaves: boolean,
projects: Array<{
binsDir: string,
buildIndex: number,
@@ -246,15 +244,6 @@ export default async (opts: HeadlessOptions) => {
let newHoistedAliases!: {[depPath: string]: string[]}
if (rootImporterWithFlatModules) {
newHoistedAliases = await hoist(matcher(opts.hoistPattern!), {
getIndependentPackageLocation: opts.independentLeaves
? async (packageId: string, packageName: string) => {
const { dir } = await opts.storeController.getPackageLocation(packageId, packageName, {
lockfileDir,
targetEngine: opts.sideEffectsCacheRead && ENGINE_NAME || undefined,
})
return dir
}
: undefined,
lockfile: filteredLockfile,
lockfileDir,
modulesDir: hoistedModulesDir,
@@ -341,7 +330,6 @@ export default async (opts: HeadlessOptions) => {
hoistedAliases: newHoistedAliases,
hoistPattern: opts.hoistPattern,
included: opts.include,
independentLeaves: !!opts.independentLeaves,
layoutVersion: LAYOUT_VERSION,
packageManager: `${opts.packageManager.name}@${opts.packageManager.version}`,
pendingBuilds: opts.pendingBuilds,
@@ -468,7 +456,6 @@ async function linkRootPackages (
interface LockfileToDepGraphOptions {
force: boolean,
include: IncludedDependencies,
independentLeaves: boolean,
importerIds: string[],
lockfileDir: string,
skipped: Set<string>,
@@ -497,15 +484,8 @@ async function lockfileToDepGraph (
const pkgName = nameVerFromPkgSnapshot(depPath, pkgSnapshot).name
const modules = path.join(opts.virtualStoreDir, pkgIdToFilename(depPath, opts.lockfileDir), 'node_modules')
const packageId = packageIdFromSnapshot(depPath, pkgSnapshot, opts.registries)
const pkgLocation = await opts.storeController.getPackageLocation(packageId, pkgName, {
lockfileDir: opts.lockfileDir,
targetEngine: opts.sideEffectsCacheRead && !opts.force && ENGINE_NAME || undefined,
})
const independent = opts.independentLeaves && packageIsIndependent(pkgSnapshot)
const peripheralLocation = !independent
? path.join(modules, pkgName)
: pkgLocation.dir
const peripheralLocation = path.join(modules, pkgName)
if (
currentPackages[depPath] && R.equals(currentPackages[depPath].dependencies, lockfile.packages![depPath].dependencies) &&
R.equals(currentPackages[depPath].optionalDependencies, lockfile.packages![depPath].optionalDependencies)
@@ -551,7 +531,6 @@ async function lockfileToDepGraph (
finishing: fetchResponse.finishing,
hasBin: pkgSnapshot.hasBin === true,
hasBundledDependencies: !!pkgSnapshot.bundledDependencies,
independent,
modules,
name: pkgName,
optional: !!pkgSnapshot.optional,
@@ -567,7 +546,6 @@ async function lockfileToDepGraph (
const ctx = {
force: opts.force,
graph,
independentLeaves: opts.independentLeaves,
lockfileDir: opts.lockfileDir,
pkgSnapshotsByDepPaths: lockfile.packages,
registries: opts.registries,
@@ -605,7 +583,6 @@ async function getChildrenPaths (
force: boolean,
registries: Registries,
virtualStoreDir: string,
independentLeaves: boolean,
storeDir: string,
skipped: Set<string>,
pkgSnapshotsByDepPaths: Record<string, PackageSnapshot>,
@@ -627,18 +604,8 @@ async function getChildrenPaths (
if (ctx.graph[childRelDepPath]) {
children[alias] = ctx.graph[childRelDepPath].peripheralLocation
} else if (childPkgSnapshot) {
if (ctx.independentLeaves && packageIsIndependent(childPkgSnapshot)) {
const pkgId = childPkgSnapshot.id || childDepPath
const pkgName = nameVerFromPkgSnapshot(childRelDepPath, childPkgSnapshot).name
const pkgLocation = await ctx.storeController.getPackageLocation(pkgId, pkgName, {
lockfileDir: ctx.lockfileDir,
targetEngine: ctx.sideEffectsCacheRead && !ctx.force && ENGINE_NAME || undefined,
})
children[alias] = pkgLocation.dir
} else {
const pkgName = nameVerFromPkgSnapshot(childRelDepPath, childPkgSnapshot).name
children[alias] = path.join(ctx.virtualStoreDir, pkgIdToFilename(childRelDepPath, ctx.lockfileDir), 'node_modules', pkgName)
}
const pkgName = nameVerFromPkgSnapshot(childRelDepPath, childPkgSnapshot).name
children[alias] = path.join(ctx.virtualStoreDir, pkgIdToFilename(childRelDepPath, ctx.lockfileDir), 'node_modules', pkgName)
} else if (allDeps[alias].indexOf('file:') === 0) {
children[alias] = path.resolve(ctx.lockfileDir, allDeps[alias].substr(5))
} else if (!ctx.skipped.has(childRelDepPath)) {
@@ -656,9 +623,6 @@ export interface DependenciesGraphNode {
finishing: () => Promise<void>,
peripheralLocation: string,
children: {[alias: string]: string},
// an independent package is a package that
// has neither regular nor peer dependencies
independent: boolean,
optionalDependencies: Set<string>,
optional: boolean,
depPath: string, // this option is only needed for saving pendingBuild when running with --ignore-scripts flag
@@ -754,7 +718,6 @@ async function linkAllModules (
) {
return Promise.all(
depNodes
.filter(({ independent }) => !independent)
.map(async (depNode) => {
const childrenToLink = opts.optional
? depNode.children

View File

@@ -42,8 +42,7 @@ test('installing a simple project', async (t) => {
t.ok(project.requireModule('is-negative'), 'dev dep installed')
t.ok(project.requireModule('colors'), 'optional dep installed')
// test that independent leaves is false by default
await project.has(`.pnpm/colors@1.2.0`) // colors is not symlinked from the store
await project.has(`.pnpm/colors@1.2.0`)
await project.isExecutable('.bin/rimraf')
@@ -245,70 +244,6 @@ test('not installing optional deps', async (t) => {
t.end()
})
// Covers https://github.com/pnpm/pnpm/issues/1547
test('installing with independent-leaves and hoistPattern=*', async (t) => {
const lockfileDir = path.join(fixtures, 'with-1-dep')
await rimraf(path.join(lockfileDir, 'node_modules'))
const { projects } = await readprojectsContext(
[
{
rootDir: lockfileDir,
},
],
{ lockfileDir }
)
await headless(await testDefaults({
hoistPattern: '*',
independentLeaves: true,
lockfileDir: lockfileDir,
projects: await Promise.all(
projects.map(async (project) => ({ ...project, manifest: await readPackageJsonFromDir(project.rootDir) }))
),
}))
const project = assertProject(t, lockfileDir)
await project.has('rimraf')
await project.has('.pnpm/node_modules/glob')
await project.has('.pnpm/node_modules/path-is-absolute')
// wrappy is linked directly from the store
await project.hasNot(`.pnpm/wrappy@1.0.2`)
await project.storeHas('wrappy', '1.0.2')
await project.has(`.pnpm/rimraf@2.5.1`)
await project.isExecutable('.bin/rimraf')
t.end()
})
test('installing with independent-leaves when an optional subdep is skipped', async (t) => {
const prefix = path.join(fixtures, 'has-incompatible-optional-subdep')
await rimraf(path.join(prefix, 'node_modules'))
await headless(await testDefaults({
independentLeaves: true,
lockfileDir: prefix,
}))
const modulesInfo = await readYamlFile<{ skipped: string[] }>(path.join(prefix, 'node_modules', '.modules.yaml'))
t.deepEqual(
modulesInfo.skipped,
[
'/dep-of-optional-pkg/1.0.0',
'/not-compatible-with-any-os/1.0.0',
],
'optional subdeps skipped'
)
const project = assertProject(t, prefix)
await project.has('pkg-with-optional')
t.end()
})
test('run pre/postinstall scripts', async (t) => {
const prefix = path.join(fixtures, 'deps-have-lifecycle-scripts')
const outputJsonPath = path.join(prefix, 'output.json')
@@ -544,53 +479,6 @@ test('installation of a dependency that has a resolved peer in subdeps', async (
t.end()
})
test('independent-leaves: installing a simple project', async (t) => {
const prefix = path.join(fixtures, 'simple')
await rimraf(path.join(prefix, 'node_modules'))
const reporter = sinon.spy()
await headless(await testDefaults({ lockfileDir: prefix, reporter, independentLeaves: true }))
const project = assertProject(t, prefix)
t.ok(project.requireModule('is-positive'), 'prod dep installed')
t.ok(project.requireModule('rimraf'), 'prod dep installed')
t.ok(project.requireModule('is-negative'), 'dev dep installed')
t.ok(project.requireModule('colors'), 'optional dep installed')
await project.has(`.pnpm/rimraf@2.7.1`) // rimraf is not symlinked from the store
await project.hasNot(`.pnpm/colors@1.2.0`) // colors is symlinked from the store
await project.isExecutable('.bin/rimraf')
t.ok(await project.readCurrentLockfile())
t.ok(await project.readModulesManifest())
t.ok(reporter.calledWithMatch({
level: 'debug',
name: 'pnpm:package-manifest',
updated: require(path.join(prefix, 'package.json')),
} as PackageManifestLog), 'updated package.json logged')
t.ok(reporter.calledWithMatch({
added: 15,
level: 'debug',
name: 'pnpm:stats',
prefix,
} as StatsLog), 'added stat')
t.ok(reporter.calledWithMatch({
level: 'debug',
name: 'pnpm:stats',
prefix,
removed: 0,
} as StatsLog), 'removed stat')
t.ok(reporter.calledWithMatch({
level: 'debug',
name: 'pnpm:stage',
prefix,
stage: 'importing_done',
} as StageLog), 'importing stage done logged')
t.end()
})
test('installing with hoistPattern=*', async (t) => {
const prefix = path.join(fixtures, 'simple-shamefully-flatten')
const reporter = sinon.spy()
@@ -604,8 +492,7 @@ test('installing with hoistPattern=*', async (t) => {
t.ok(project.requireModule('is-negative'), 'dev dep installed')
t.ok(project.requireModule('colors'), 'optional dep installed')
// test that independent leaves is false by default
await project.has(`.pnpm/colors@1.2.0`) // colors is not symlinked from the store
await project.has(`.pnpm/colors@1.2.0`)
await project.isExecutable('.bin/rimraf')
await project.isExecutable('.pnpm/node_modules/.bin/hello-world-js-bin')
@@ -664,8 +551,7 @@ test('installing with hoistPattern=* and shamefullyHoist=true', async (t) => {
t.ok(project.requireModule('is-negative'), 'dev dep installed')
t.ok(project.requireModule('colors'), 'optional dep installed')
// test that independent leaves is false by default
await project.has(`.pnpm/colors@1.2.0`) // colors is not symlinked from the store
await project.has(`.pnpm/colors@1.2.0`)
await project.isExecutable('.bin/rimraf')
await project.isExecutable('.bin/hello-world-js-bin')
@@ -835,34 +721,3 @@ test('installing in a workspace', async (t) => {
t.end()
})
test('independent-leaves: installing in a workspace', async (t) => {
const workspaceFixture = path.join(__dirname, 'workspace-fixture2')
const { projects } = await readprojectsContext(
[
{
rootDir: path.join(workspaceFixture, 'foo'),
},
{
rootDir: path.join(workspaceFixture, 'bar'),
},
],
{ lockfileDir: workspaceFixture }
)
await headless(await testDefaults({
independentLeaves: true,
lockfileDir: workspaceFixture,
projects: await Promise.all(
projects.map(async (project) => ({ ...project, manifest: await readPackageJsonFromDir(project.rootDir) }))
),
}))
const projectBar = assertProject(t, path.join(workspaceFixture, 'bar'))
await projectBar.has('foo')
t.ok(await exists(path.join(workspaceFixture, `node_modules/.pnpm/express@4.16.4/node_modules/array-flatten`)), 'independent package linked')
t.end()
})

View File

@@ -65,7 +65,6 @@ export default async function testDefaults (
engineStrict: false,
force: false,
include,
independentLeaves: false,
lockfileDir,
packageManager: {
name: 'pnpm',

View File

@@ -3,7 +3,6 @@ import linkBins, { WarnFunction } from '@pnpm/link-bins'
import {
Lockfile,
nameVerFromPkgSnapshot,
packageIsIndependent,
} from '@pnpm/lockfile-utils'
import lockfileWalker, { LockfileWalkerStep } from '@pnpm/lockfile-walker'
import logger from '@pnpm/logger'
@@ -17,7 +16,6 @@ import R = require('ramda')
export default async function hoistByLockfile (
match: (dependencyName: string) => boolean,
opts: {
getIndependentPackageLocation?: (packageId: string, packageName: string) => Promise<string>,
lockfile: Lockfile,
lockfileDir: string,
modulesDir: string,
@@ -48,7 +46,6 @@ export default async function hoistByLockfile (
step,
0,
{
getIndependentPackageLocation: opts.getIndependentPackageLocation,
lockfileDir: opts.lockfileDir,
registries: opts.registries,
virtualStoreDir: opts.virtualStoreDir,
@@ -83,7 +80,6 @@ async function getDependencies (
step: LockfileWalkerStep,
depth: number,
opts: {
getIndependentPackageLocation?: (packageId: string, packageName: string) => Promise<string>,
registries: Registries,
lockfileDir: string,
virtualStoreDir: string,
@@ -92,10 +88,8 @@ async function getDependencies (
const deps: Dependency[] = []
const nextSteps: LockfileWalkerStep[] = []
for (const { pkgSnapshot, relDepPath, next } of step.dependencies) {
const absolutePath = dp.resolve(opts.registries, relDepPath)
const pkgName = nameVerFromPkgSnapshot(relDepPath, pkgSnapshot).name
const modules = path.join(opts.virtualStoreDir, pkgIdToFilename(relDepPath, opts.lockfileDir), 'node_modules')
const independent = opts.getIndependentPackageLocation && packageIsIndependent(pkgSnapshot)
const allDeps = {
...pkgSnapshot.dependencies,
...pkgSnapshot.optionalDependencies,
@@ -107,9 +101,7 @@ async function getDependencies (
}, {}),
depPath: relDepPath,
depth,
location: !independent
? path.join(modules, pkgName)
: await opts.getIndependentPackageLocation!(pkgSnapshot.id || absolutePath, pkgName),
location: path.join(modules, pkgName),
})
nextSteps.push(next())

View File

@@ -1,4 +1,3 @@
independentLeaves: false
layoutVersion: 1
packageManager: pnpm@1.4.0
skipped: []

View File

@@ -14,9 +14,7 @@ export default async function getPkgInfo (
try {
manifest = await readPkg(path.join(pkg.path, 'node_modules', pkg.name, 'package.json'))
} catch (err) {
// This is a temporary workaround.
// If the package.json is not found inside node_modules, it should be read from the store.
// This frequently happens when the independent-leaves config is true.
// This will probably never happen
manifest = {
description: '[Could not find additional info about this dependency]',
}

View File

@@ -6,7 +6,6 @@ included:
dependencies: true
devDependencies: true
optionalDependencies: true
independentLeaves: false
layoutVersion: 1
packageManager: pnpm@2.17.0-4
pendingBuilds: []

View File

@@ -2,7 +2,6 @@ included:
dependencies: true
devDependencies: true
optionalDependencies: true
independentLeaves: true
layoutVersion: 3
packageManager: pnpm@3.8.1
pendingBuilds: []

View File

@@ -2,7 +2,6 @@ included:
dependencies: true
devDependencies: true
optionalDependencies: true
independentLeaves: true
layoutVersion: 3
packageManager: pnpm@3.8.1
pendingBuilds: []

View File

@@ -2,7 +2,6 @@ included:
dependencies: true
devDependencies: true
optionalDependencies: true
independentLeaves: true
layoutVersion: 3
packageManager: pnpm@3.8.1
pendingBuilds: []

View File

@@ -2,7 +2,6 @@ included:
dependencies: true
devDependencies: true
optionalDependencies: true
independentLeaves: true
layoutVersion: 3
packageManager: pnpm@3.8.1
pendingBuilds: []

View File

@@ -19,13 +19,12 @@ import {write, read} from '@pnpm/modules-yaml'
await write('node_modules', {
hoistedAliases: {}
independentLeaves: false,
layoutVersion: 1,
packageManager: 'pnpm@1.0.0',
pendingBuilds: [],
shamefullyFlatten: false,
skipped: [],
store: '/home/user/.pnpm-store',
storeDir: '/home/user/.pnpm-store',
})
const modulesYaml = await read(`node_modules`)

View File

@@ -16,7 +16,6 @@ export interface Modules {
hoistedAliases: {[depPath: string]: string[]}
hoistPattern?: string[]
included: IncludedDependencies,
independentLeaves: boolean,
layoutVersion: number,
packageManager: string,
pendingBuilds: string[],

View File

@@ -15,7 +15,6 @@ test('write() and read()', async (t) => {
devDependencies: true,
optionalDependencies: true,
},
independentLeaves: false,
layoutVersion: 1,
packageManager: 'pnpm@2',
pendingBuilds: [],

View File

@@ -1,9 +1,5 @@
import packageRequester from './packageRequester'
export {
getCacheByEngine,
} from './packageRequester'
export default packageRequester
export { PackageResponse, PackageFilesResponse } from '@pnpm/store-controller-types'

View File

@@ -198,7 +198,6 @@ async function resolveAndFetch (
return {
body: {
id,
inStoreLocation: path.join(ctx.storeDir, pkgIdToFilename(id, options.lockfileDir)),
isLocal: false as const,
latest,
manifest,
@@ -221,7 +220,6 @@ async function resolveAndFetch (
return {
body: {
id,
inStoreLocation: fetchResult.inStoreLocation,
isLocal: false as const,
latest,
manifest,
@@ -245,7 +243,6 @@ type FetchLock = {
files: Promise<PackageFilesResponse>,
filesIndexFile: string,
finishing: Promise<void>,
inStoreLocation: string,
}
function fetchToStore (
@@ -278,7 +275,6 @@ function fetchToStore (
filesIndexFile: string,
files: () => Promise<PackageFilesResponse>,
finishing: () => Promise<void>,
inStoreLocation: string,
} {
const targetRelative = pkgIdToFilename(opts.pkgId, opts.lockfileDir)
const target = path.join(ctx.storeDir, targetRelative)
@@ -299,14 +295,12 @@ function fetchToStore (
files: removeKeyOnFail(files.promise),
filesIndexFile,
finishing: removeKeyOnFail(finishing.promise),
inStoreLocation: target,
})
} else {
ctx.fetchingLocker.set(opts.pkgId, {
files: removeKeyOnFail(files.promise),
filesIndexFile,
finishing: removeKeyOnFail(finishing.promise),
inStoreLocation: target,
})
}
@@ -358,7 +352,6 @@ function fetchToStore (
files: pShare(result.files),
filesIndexFile: result.filesIndexFile,
finishing: pShare(result.finishing),
inStoreLocation: result.inStoreLocation,
}
async function removeKeyOnFail<T> (p: Promise<T>): Promise<T> {
@@ -551,24 +544,3 @@ async function fetcher (
throw err
}
}
// TODO: cover with tests
export async function getCacheByEngine (storeDir: string, id: string): Promise<Map<string, string>> {
const map = new Map<string, string>()
const cacheRoot = path.join(storeDir, id, 'side_effects')
if (!await fs.exists(cacheRoot)) {
return map
}
const dirContents = (await fs.readdir(cacheRoot)).map((content: string) => path.join(cacheRoot, content))
await Promise.all(dirContents.map(async (dir: string) => {
if (!(await fs.lstat(dir)).isDirectory()) {
return
}
const engineName = path.basename(dir)
map[engineName] = path.join(dir, 'package')
}))
return map
}

View File

@@ -61,7 +61,6 @@ test('request package', async t => {
t.equal(pkgResponse.body.id, 'registry.npmjs.org/is-positive/1.0.0', 'responded with correct package ID')
t.equal(pkgResponse.body.resolvedVia, 'npm-registry', 'responded with correct resolvedVia')
t.equal(pkgResponse.body.inStoreLocation, path.join(storeDir, 'registry.npmjs.org', 'is-positive@1.0.0'), 'package location in store returned')
t.equal(pkgResponse.body.isLocal, false, 'package is not local')
t.equal(typeof pkgResponse.body.latest, 'string', 'latest is returned')
t.equal(pkgResponse.body.manifest.name, 'is-positive', 'package manifest returned')
@@ -104,7 +103,6 @@ test('request package but skip fetching', async t => {
t.ok(pkgResponse.body, 'response has body')
t.equal(pkgResponse.body.id, 'registry.npmjs.org/is-positive/1.0.0', 'responded with correct package ID')
t.equal(pkgResponse.body.inStoreLocation, path.join('.store', 'registry.npmjs.org', 'is-positive@1.0.0'), 'package location in store returned')
t.equal(pkgResponse.body.isLocal, false, 'package is not local')
t.equal(typeof pkgResponse.body.latest, 'string', 'latest is returned')
t.equal(pkgResponse.body.manifest.name, 'is-positive', 'package manifest returned')
@@ -146,7 +144,6 @@ test('request package but skip fetching, when resolution is already available',
update: false,
}) as PackageResponse & {
body: {
inStoreLocation: string,
latest: string,
manifest: {name: string},
},
@@ -158,7 +155,6 @@ test('request package but skip fetching, when resolution is already available',
t.ok(pkgResponse.body, 'response has body')
t.equal(pkgResponse.body.id, 'registry.npmjs.org/is-positive/1.0.0', 'responded with correct package ID')
t.equal(pkgResponse.body.inStoreLocation, path.join('.store', 'registry.npmjs.org', 'is-positive@1.0.0'), 'package location in store returned')
t.equal(pkgResponse.body.isLocal, false, 'package is not local')
t.equal(typeof pkgResponse.body.latest, 'string', 'latest is returned')
t.equal(pkgResponse.body.manifest.name, 'is-positive', 'package manifest returned')

View File

@@ -20,7 +20,6 @@
"@pnpm/core-loggers": "workspace:4.0.2-alpha.0",
"@pnpm/fetcher-base": "workspace:7.0.0-alpha.3",
"@pnpm/package-requester": "workspace:12.0.0-alpha.5",
"@pnpm/pkgid-to-filename": "3.0.0",
"@pnpm/resolver-base": "workspace:7.0.1-alpha.0",
"@pnpm/store-controller-types": "workspace:8.0.0-alpha.4",
"@pnpm/types": "workspace:6.0.0-alpha.0",

View File

@@ -4,8 +4,7 @@ import {
PackageFilesIndex,
} from '@pnpm/cafs'
import { FetchFunction } from '@pnpm/fetcher-base'
import createPackageRequester, { getCacheByEngine } from '@pnpm/package-requester'
import pkgIdToFilename from '@pnpm/pkgid-to-filename'
import createPackageRequester from '@pnpm/package-requester'
import { ResolveFunction } from '@pnpm/resolver-base'
import {
ImportPackageFunction,
@@ -64,37 +63,12 @@ export default async function (
return {
close: async () => {}, // tslint:disable-line:no-empty
fetchPackage: packageRequester.fetchPackageToStore,
getPackageLocation,
importPackage,
prune: prune.bind(null, storeDir),
requestPackage: packageRequester.requestPackage,
upload,
}
async function getPackageLocation (
packageId: string,
packageName: string,
opts: {
lockfileDir: string,
targetEngine?: string,
}
) {
if (opts.targetEngine) {
const sideEffectsCacheLocation = (await getCacheByEngine(initOpts.storeDir, packageId))[opts.targetEngine]
if (sideEffectsCacheLocation) {
return {
dir: sideEffectsCacheLocation,
isBuilt: true,
}
}
}
return {
dir: path.join(initOpts.storeDir, pkgIdToFilename(packageId, opts.lockfileDir), 'node_modules', packageName),
isBuilt: false,
}
}
async function upload (builtPkgLocation: string, opts: {filesIndexFile: string, engine: string}) {
const sideEffectsIndex = await packageRequester.cafs.addFilesFromDir(builtPkgLocation)
// TODO: move this to a function

View File

@@ -21,7 +21,6 @@ export function rcOptionsTypes () {
'ignore-pnpmfile',
'ignore-scripts',
'ignore-workspace-root-check',
'independent-leaves',
'link-workspace-packages',
'lockfile-dir',
'lockfile-directory',

View File

@@ -22,7 +22,6 @@ export function rcOptionsTypes () {
'hoist-pattern',
'ignore-pnpmfile',
'ignore-scripts',
'independent-leaves',
'link-workspace-packages',
'lockfile-dir',
'lockfile-directory',
@@ -158,10 +157,6 @@ export function help () {
description: 'Disable pnpm hooks defined in pnpmfile.js',
name: '--ignore-pnpmfile',
},
{
description: 'Symlinks leaf dependencies directly from the global store',
name: '--independent-leaves',
},
{
description: "If false, doesn't check whether packages in the store were mutated",
name: '--[no-]verify-store-integrity',
@@ -260,7 +255,6 @@ export type InstallCommandOptions = Pick<Config,
| 'globalPnpmfile'
| 'ignorePnpmfile'
| 'ignoreScripts'
| 'independentLeaves'
| 'linkWorkspacePackages'
| 'rawLocalConfig'
| 'lockfileDir'

View File

@@ -38,7 +38,6 @@ export type InstallDepsOptions = Pick<Config,
| 'globalPnpmfile'
| 'ignorePnpmfile'
| 'ignoreScripts'
| 'independentLeaves'
| 'linkWorkspacePackages'
| 'lockfileDir'
| 'lockfileOnly'
@@ -146,7 +145,6 @@ export default async function handler (
workspacePackages,
forceHoistPattern: typeof opts.rawLocalConfig['hoist-pattern'] !== 'undefined' || typeof opts.rawLocalConfig['hoist'] !== 'undefined',
forceIndependentLeaves: typeof opts.rawLocalConfig['independent-leaves'] !== 'undefined',
forceShamefullyHoist: typeof opts.rawLocalConfig['shamefully-hoist'] !== 'undefined',
}
if (!opts.ignorePnpmfile) {

View File

@@ -120,7 +120,6 @@ export default async function recursive (
workspacePackages,
forceHoistPattern: typeof opts.rawLocalConfig['hoist-pattern'] !== 'undefined' || typeof opts.rawLocalConfig['hoist'] !== 'undefined',
forceIndependentLeaves: typeof opts.rawLocalConfig['independent-leaves'] !== 'undefined',
forceShamefullyHoist: typeof opts.rawLocalConfig['shamefully-hoist'] !== 'undefined',
}) as InstallOptions

View File

@@ -81,40 +81,6 @@ test('listing packages', async (t) => {
t.end()
})
test('independent-leaves=true: pnpm list --long', async (t) => {
prepare(t, {
dependencies: {
'is-positive': '1.0.0',
},
devDependencies: {
'is-negative': '1.0.0',
},
})
await execa('node', [pnpmBin, 'install', '--independent-leaves', '--no-hoist'])
const output = await list.handler({
dir: process.cwd(),
long: true,
}, [])
// TODO: the --long flag should work with --independent-leaves
t.equal(stripAnsi(output), stripIndent`
Legend: production dependency, optional only, dev only
project@0.0.0 ${process.cwd()}
dependencies:
is-positive 1.0.0
[Could not find additional info about this dependency]
devDependencies:
is-negative 1.0.0
[Could not find additional info about this dependency]
`)
t.end()
})
test(`listing packages of a project that has an external ${WANTED_LOCKFILE}`, async (t) => {
preparePackages(t, [
{

View File

@@ -138,7 +138,6 @@ export type OutdatedCommandOptions = {
| 'fetchRetryMintimeout'
| 'global'
| 'httpsProxy'
| 'independentLeaves'
| 'key'
| 'localAddress'
| 'lockfileDir'

View File

@@ -27,7 +27,6 @@ const OUTDATED_OPTIONS = {
fetchRetryMaxtimeout: 60,
fetchRetryMintimeout: 10,
global: false,
independentLeaves: false,
networkConcurrency: 16,
offline: false,
rawConfig: { registry: REGISTRY_URL },

View File

@@ -23,7 +23,6 @@ export const DEFAULT_OPTS = {
devDependencies: true,
optionalDependencies: true,
},
independentLeaves: false,
key: undefined,
linkWorkspacePackages: true,
localAddress: undefined,

View File

@@ -175,7 +175,6 @@ export async function rebuild (
hoistedAliases: ctx.hoistedAliases,
hoistPattern: ctx.hoistPattern,
included: ctx.include,
independentLeaves: ctx.independentLeaves,
layoutVersion: LAYOUT_VERSION,
packageManager: `${opts.packageManager.name}@${opts.packageManager.version}`,
pendingBuilds: ctx.pendingBuilds,
@@ -224,7 +223,6 @@ async function _rebuild (
rootModulesDir: string,
currentLockfile: Lockfile,
projects: Array<{ id: string, rootDir: string }>,
independentLeaves: boolean,
extraBinPaths: string[],
},
opts: StrictRebuildOptions
@@ -268,24 +266,11 @@ async function _rebuild (
const pkgSnapshot = pkgSnapshots[relDepPath]
const depPath = dp.resolve(opts.registries, relDepPath)
const pkgInfo = nameVerFromPkgSnapshot(relDepPath, pkgSnapshot)
const independent = ctx.independentLeaves && packageIsIndependent(pkgSnapshot)
const pkgRoot = !independent
? path.join(ctx.virtualStoreDir, pkgIdToFilename(relDepPath, opts.lockfileDir), 'node_modules', pkgInfo.name)
: await (
async () => {
const { dir } = await opts.storeController.getPackageLocation(pkgSnapshot.id || depPath, pkgInfo.name, {
lockfileDir: opts.lockfileDir,
targetEngine: opts.sideEffectsCacheRead && !opts.force && ENGINE_NAME || undefined,
})
return dir
}
)()
const pkgRoot = path.join(ctx.virtualStoreDir, pkgIdToFilename(relDepPath, opts.lockfileDir), 'node_modules', pkgInfo.name)
try {
if (!independent) {
const modules = path.join(ctx.virtualStoreDir, pkgIdToFilename(relDepPath, opts.lockfileDir), 'node_modules')
const binPath = path.join(pkgRoot, 'node_modules', '.bin')
await linkBins(modules, binPath, { warn })
}
const modules = path.join(ctx.virtualStoreDir, pkgIdToFilename(relDepPath, opts.lockfileDir), 'node_modules')
const binPath = path.join(pkgRoot, 'node_modules', '.bin')
await linkBins(modules, binPath, { warn })
await runPostinstallHooks({
depPath,
extraBinPaths: ctx.extraBinPaths,
@@ -325,7 +310,6 @@ async function _rebuild (
.keys(pkgSnapshots)
.filter((relDepPath) => !packageIsIndependent(pkgSnapshots[relDepPath]))
.map((relDepPath) => limitLinking(() => {
const depPath = dp.resolve(opts.registries, relDepPath)
const pkgSnapshot = pkgSnapshots[relDepPath]
const pkgInfo = nameVerFromPkgSnapshot(relDepPath, pkgSnapshot)
const modules = path.join(ctx.virtualStoreDir, pkgIdToFilename(relDepPath, opts.lockfileDir), 'node_modules')

View File

@@ -70,7 +70,6 @@ export async function handler (
| 'allProjects'
| 'dir'
| 'engineStrict'
| 'independentLeaves'
| 'rawLocalConfig'
| 'registries'
| 'selectedProjectsGraph'

View File

@@ -235,46 +235,6 @@ test('rebuild dependencies in correct order', async (t) => {
t.end()
})
test('rebuild dependencies in correct order when node_modules uses independent-leaves', async (t) => {
const project = prepareEmpty(t)
const storeDir = path.resolve('store')
await execa('node', [
pnpmBin,
'add',
'with-postinstall-a',
'--registry',
REGISTRY,
'--store-dir',
storeDir,
'--ignore-scripts',
'--independent-leaves',
'--no-hoist',
])
let modules = await project.readModulesManifest()
t.ok(modules)
t.doesNotEqual(modules!.pendingBuilds.length, 0)
await project.hasNot(`.pnpm/with-postinstall-b@1.0.0/node_modules/with-postinstall-b/output.json`)
await project.hasNot('with-postinstall-a/output.json')
await rebuild.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
independentLeaves: true,
pending: true,
storeDir,
}, [])
modules = await project.readModulesManifest()
t.ok(modules)
t.equal(modules!.pendingBuilds.length, 0)
t.ok(+project.requireModule(`.pnpm/with-postinstall-b@1.0.0/node_modules/with-postinstall-b/output.json`)[0] < +project.requireModule('with-postinstall-a/output.json')[0])
t.end()
})
test('rebuild links bins', async (t) => {
const project = prepareEmpty(t)
const storeDir = path.resolve('store')

View File

@@ -7,7 +7,6 @@ export interface StrictStoreStatusOptions {
lockfileDir: string,
dir: string,
storeDir: string,
independentLeaves: boolean,
force: boolean,
forceSharedLockfile: boolean,
useLockfile: boolean,
@@ -32,7 +31,6 @@ const defaults = async (opts: StoreStatusOptions) => {
dir,
force: false,
forceSharedLockfile: false,
independentLeaves: false,
lockfileDir,
registries: DEFAULT_REGISTRIES,
shamefullyHoist: false,

View File

@@ -29,7 +29,7 @@ export function help () {
],
},
],
usages: ['pnpm root [-g [--independent-leaves]]'],
usages: ['pnpm root [-g]'],
})
}

View File

@@ -94,18 +94,6 @@ test('command fails when an unsupported flag is used', async (t) => {
t.ok(stderr.toString().includes("Unknown option 'save-dev'"))
})
test('adding new dep does not fail if node_modules was created with --no-hoist and --independent-leaves', async (t: tape.Test) => {
const project = prepare(t)
await execPnpm(['add', 'is-positive', '--no-hoist', '--independent-leaves'])
t.equal(execPnpmSync(['add', 'is-negative', '--hoist']).status, 1)
t.equal(execPnpmSync(['add', 'is-negative', '--no-independent-leaves']).status, 1)
t.equal(execPnpmSync(['add', 'is-negative']).status, 0)
await project.has('is-negative')
})
test('adding new dep does not fail if node_modules was created with --hoist-pattern=eslint-* and --shamefully-hoist', async (t: tape.Test) => {
const project = prepare(t)

View File

@@ -86,7 +86,6 @@ function createEnv (opts?: {storeDir?: string}): NodeJS.ProcessEnv {
const env = {
npm_config_fetch_retries: '4',
npm_config_hoist: 'true',
npm_config_independent_leaves: 'false',
npm_config_registry: `http://localhost:${REGISTRY_MOCK_PORT}/`,
npm_config_silent: 'true',
npm_config_store_dir: opts && opts.storeDir || '../store',

View File

@@ -25,7 +25,6 @@ export default async function <T>(
id: string,
} & T & Required<ProjectOptions>>,
include: Record<DependenciesField, boolean>,
independentLeaves: boolean | undefined,
modules: Modules | null,
pendingBuilds: string[],
registries: Registries | null | undefined,
@@ -41,7 +40,6 @@ export default async function <T>(
hoist: !modules ? undefined : Boolean(modules.hoistPattern),
hoistedAliases: modules?.hoistedAliases || {},
include: modules?.included || { dependencies: true, devDependencies: true, optionalDependencies: true },
independentLeaves: modules?.independentLeaves || undefined,
modules,
pendingBuilds: modules?.pendingBuilds || [],
projects: await Promise.all(

View File

@@ -175,14 +175,12 @@ export interface ResolvedPackage {
fetchingBundledManifest?: () => Promise<DependencyManifest>,
filesIndexFile: string,
finishing: () => Promise<void>,
path: string,
name: string,
version: string,
peerDependencies: Dependencies,
optionalDependencies: Set<string>,
hasBin: boolean,
hasBundledDependencies: boolean,
independent: boolean,
prepare: boolean,
depPath: string,
requiresBuild: boolean | undefined, // added to fix issue #1201
@@ -784,13 +782,9 @@ function getResolvedPackage (
hasBin: options.hasBin,
hasBundledDependencies: !!(options.pkg.bundledDependencies || options.pkg.bundleDependencies),
id: options.pkgResponse.body.id,
independent: (options.pkg.dependencies === undefined || R.isEmpty(options.pkg.dependencies)) &&
(options.pkg.optionalDependencies === undefined || R.isEmpty(options.pkg.optionalDependencies)) &&
(options.pkg.peerDependencies === undefined || R.isEmpty(options.pkg.peerDependencies)),
name: options.pkg.name,
optional: options.wantedDependency.optional,
optionalDependencies: new Set(R.keys(options.pkg.optionalDependencies)),
path: options.pkgResponse.body.inStoreLocation!,
peerDependencies: peerDependencies ?? {},
prepare: options.prepare,
prod: !options.wantedDependency.dev && !options.wantedDependency.optional,

View File

@@ -30,20 +30,6 @@ export default function (
resolve({
close: async () => { return },
fetchPackage: fetchPackage.bind(null, remotePrefix, limitedFetch),
getPackageLocation: async (
packageId: string,
packageName: string,
opts: {
lockfileDir: string,
targetEngine?: string,
}
): Promise<{ dir: string, isBuilt: boolean }> => {
return await limitedFetch(`${remotePrefix}/getPackageLocation`, {
opts,
packageId,
packageName,
}) as { dir: string, isBuilt: boolean }
},
importPackage: async (to: string, opts: {
filesResponse: PackageFilesResponse,
force: boolean,

View File

@@ -103,7 +103,7 @@ export default function (
if (pkgResponse['files']) { // tslint:disable-line
filesPromises[body.msgId] = pkgResponse['files'] // tslint:disable-line
}
res.end(JSON.stringify({ inStoreLocation: pkgResponse.inStoreLocation }))
res.end(JSON.stringify({ filesIndexFile: pkgResponse.filesIndexFile }))
} catch (err) {
res.end(JSON.stringify({
error: {
@@ -158,12 +158,6 @@ export default function (
res.end(JSON.stringify('OK'))
globalInfo('Server stopped')
break
case '/getPackageLocation': {
const { packageId, packageName, opts } = (await bodyPromise) as any // tslint:disable-line:no-any
const pkgLocation = await store.getPackageLocation(packageId, packageName, opts)
res.end(JSON.stringify(pkgLocation))
break
}
default:
res.statusCode = 404
const error = { error: `${req.url} does not match any route` }

View File

@@ -103,7 +103,7 @@ test('fetchPackage', async t => {
},
})
t.equal(typeof response.inStoreLocation, 'string', 'location in store returned')
t.equal(typeof response.filesIndexFile, 'string', 'index file location in store returned')
t.ok(await response.bundledManifest!())
@@ -116,16 +116,6 @@ test('fetchPackage', async t => {
t.comment('getPackageLocation()')
t.deepEqual(
await storeCtrl.getPackageLocation(pkgId, 'is-positive', {
lockfileDir: process.cwd(),
}),
{
dir: path.join(storeDir, 'registry.npmjs.org/is-positive@1.0.0/node_modules/is-positive'),
isBuilt: false,
}
)
await server.close()
await storeCtrl.close()
t.end()

View File

@@ -29,14 +29,6 @@ export type BundledManifest = Pick<
>
export interface StoreController {
getPackageLocation (
packageId: string,
packageName: string,
opts: {
lockfileDir: string,
targetEngine?: string,
}
): Promise<{ dir: string, isBuilt: boolean }>,
requestPackage: RequestPackageFunction,
fetchPackage: FetchPackageToStoreFunction,
importPackage: ImportPackageFunction,
@@ -52,7 +44,6 @@ export type FetchPackageToStoreFunction = (
filesIndexFile: string,
files: () => Promise<PackageFilesResponse>,
finishing: () => Promise<void>,
inStoreLocation: string,
}
export interface FetchPackageToStoreOptions {
@@ -118,7 +109,6 @@ export type PackageResponse = {
normalizedPref?: string,
updated: boolean,
resolvedVia?: string,
inStoreLocation?: string,
// This is useful for recommending updates.
// If latest does not equal the version of the
// resolved package, it is out-of-date.

View File

@@ -71,9 +71,6 @@ export interface StrictInstallOptions {
shamefullyHoist: boolean,
forceShamefullyHoist: boolean,
independentLeaves: boolean,
forceIndependentLeaves: boolean,
global: boolean,
}
@@ -106,7 +103,6 @@ const defaults = async (opts: InstallOptions) => {
devDependencies: true,
optionalDependencies: true,
},
independentLeaves: false,
lockfileDir: opts.lockfileDir || opts.dir || process.cwd(),
lockfileOnly: false,
nodeVersion: process.version,

View File

@@ -194,7 +194,6 @@ export async function mutateModules (
hoistPattern: ctx.hoistPattern,
ignoreScripts: opts.ignoreScripts,
include: opts.include,
independentLeaves: opts.independentLeaves,
lockfileDir: ctx.lockfileDir,
modulesDir: opts.modulesDir,
ownLifecycleHooksStdio: opts.ownLifecycleHooksStdio,
@@ -428,9 +427,7 @@ export async function mutateModules (
async function isExternalLink (storeDir: string, modules: string, pkgName: string) {
const link = await isInnerLink(modules, pkgName)
// checking whether the link is pointing to the store is needed
// because packages are linked to store when independent-leaves = true
return !link.isInner && !isSubdir(storeDir, link.target)
return !link.isInner
}
function pkgHasDependencies (manifest: ProjectManifest) {
@@ -712,7 +709,6 @@ async function installInContext (
hoistedModulesDir: ctx.hoistedModulesDir,
hoistPattern: ctx.hoistPattern,
include: opts.include,
independentLeaves: opts.independentLeaves,
lockfileDir: opts.lockfileDir,
makePartialCurrentLockfile: opts.makePartialCurrentLockfile,
outdatedDependencies,
@@ -818,7 +814,6 @@ async function installInContext (
hoistedAliases: result.newHoistedAliases,
hoistPattern: ctx.hoistPattern,
included: ctx.include,
independentLeaves: ctx.independentLeaves,
layoutVersion: LAYOUT_VERSION,
packageManager: `${opts.packageManager.name}@${opts.packageManager.version}`,
pendingBuilds: ctx.pendingBuilds,

View File

@@ -64,7 +64,6 @@ export default async function linkPackages (
hoistedModulesDir: string,
hoistPattern?: string[],
include: IncludedDependencies,
independentLeaves: boolean,
lockfileDir: string,
makePartialCurrentLockfile: boolean,
outdatedDependencies: {[pkgId: string]: string},
@@ -94,7 +93,6 @@ export default async function linkPackages (
// logger.info(`Creating dependency graph`)
const { depGraph, projectsDirectPathsByAlias } = resolvePeers({
dependenciesTree,
independentLeaves: opts.independentLeaves,
lockfileDir: opts.lockfileDir,
projects,
strictPeerDependencies: opts.strictPeerDependencies,
@@ -308,15 +306,6 @@ export default async function linkPackages (
let newHoistedAliases: Record<string, string[]> = {}
if (opts.hoistPattern && (newDepPaths.length > 0 || removedDepPaths.size > 0)) {
newHoistedAliases = await hoist(matcher(opts.hoistPattern!), {
getIndependentPackageLocation: opts.independentLeaves
? async (packageId: string, packageName: string) => {
const { dir } = await opts.storeController.getPackageLocation(packageId, packageName, {
lockfileDir: opts.lockfileDir,
targetEngine: opts.sideEffectsCacheRead && ENGINE_NAME || undefined,
})
return dir
}
: undefined,
lockfile: currentLockfile,
lockfileDir: opts.lockfileDir,
modulesDir: opts.hoistedModulesDir,
@@ -501,7 +490,6 @@ async function linkAllModules (
) {
return Promise.all(
depNodes
.filter(({ independent }) => !independent)
.map(async ({ children, optionalDependencies, name, modules }) => {
const childrenToLink = opts.optional
? children

View File

@@ -31,9 +31,6 @@ export interface DependenciesGraphNode {
resolution: Resolution,
peripheralLocation: string,
children: {[alias: string]: string},
// an independent package is a package that
// has neither regular nor peer dependencies
independent: boolean,
optionalDependencies: Set<string>,
depth: number,
depPath: string,
@@ -75,7 +72,6 @@ export default function (
id: string,
}>,
dependenciesTree: DependenciesTree,
independentLeaves: boolean,
virtualStoreDir: string,
lockfileDir: string,
strictPeerDependencies: boolean,
@@ -112,7 +108,6 @@ export default function (
resolvePeersOfChildren(directNodeIdsByAlias, pkgsByName, {
dependenciesTree: opts.dependenciesTree,
depGraph,
independentLeaves: opts.independentLeaves,
lockfileDir: opts.lockfileDir,
pathsByNodeId,
purePkgs: new Set(),
@@ -149,7 +144,6 @@ function resolvePeersOfNode (
dependenciesTree: DependenciesTree,
pathsByNodeId: {[nodeId: string]: string},
depGraph: DependenciesGraph,
independentLeaves: boolean,
virtualStoreDir: string,
purePkgs: Set<string>, // pure packages are those that don't rely on externally resolved peers
rootDir: string,
@@ -216,11 +210,7 @@ function resolvePeersOfNode (
ctx.pathsByNodeId[nodeId] = depPath
if (!ctx.depGraph[depPath] || ctx.depGraph[depPath].depth > node.depth) {
const independent = ctx.independentLeaves && resolvedPackage.independent
const centralLocation = path.join(resolvedPackage.path, 'node_modules', resolvedPackage.name)
const peripheralLocation = !independent
? path.join(modules, resolvedPackage.name)
: centralLocation
const peripheralLocation = path.join(modules, resolvedPackage.name)
const unknownPeers = Object.keys(unknownResolvedPeersOfChildren)
if (unknownPeers.length) {
@@ -244,7 +234,6 @@ function resolvePeersOfNode (
filesIndexFile: resolvedPackage.filesIndexFile,
hasBin: resolvedPackage.hasBin,
hasBundledDependencies: resolvedPackage.hasBundledDependencies,
independent,
installable: node.installable,
isPure,
modules,
@@ -270,7 +259,6 @@ function resolvePeersOfChildren (
parentPkgs: ParentRefs,
ctx: {
pathsByNodeId: {[nodeId: string]: string},
independentLeaves: boolean,
virtualStoreDir: string,
purePkgs: Set<string>,
depGraph: DependenciesGraph,

View File

@@ -28,9 +28,6 @@ interface StrictLinkOptions {
shamefullyHoist: boolean,
forceShamefullyHoist: boolean,
independentLeaves: boolean,
forceIndependentLeaves: boolean,
}
export type LinkOptions = Partial<StrictLinkOptions> &
@@ -58,7 +55,6 @@ async function defaults (opts: LinkOptions) {
force: false,
forceSharedLockfile: false,
hoistPattern: undefined,
independentLeaves: false,
lockfileDir: opts.lockfileDir || dir,
registries: DEFAULT_REGISTRIES,
shamefullyHoist: false,

View File

@@ -52,7 +52,7 @@ test("don't fail on non-compatible node_modules when forced in a workspace", asy
process.chdir('..')
await fs.writeFile('node_modules/.modules.yaml', `packageManager: pnpm@${3}\nstore: ${opts.storeDir}\nindependentLeaves: false\nlayoutVersion: 1`)
await fs.writeFile('node_modules/.modules.yaml', `packageManager: pnpm@${3}\nstore: ${opts.storeDir}\nlayoutVersion: 1`)
await install(manifest, { ...opts, dir: path.resolve('pkg'), lockfileDir: process.cwd() })
@@ -108,7 +108,7 @@ test('do not fail on non-compatible store when forced during named installation'
async function saveModulesYaml (pnpmVersion: string, storeDir: string) {
await fs.mkdir('node_modules')
await fs.writeFile('node_modules/.modules.yaml', `packageManager: pnpm@${pnpmVersion}\nstoreDir: ${storeDir}\nindependentLeaves: false`)
await fs.writeFile('node_modules/.modules.yaml', `packageManager: pnpm@${pnpmVersion}\nstoreDir: ${storeDir}`)
}
test(`fail on non-compatible ${WANTED_LOCKFILE}`, async (t: tape.Test) => {

View File

@@ -1,83 +0,0 @@
import { prepareEmpty } from '@pnpm/prepare'
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
import isSubdir = require('is-subdir')
import path = require('path')
import resolveLinkTarget = require('resolve-link-target')
import { addDependenciesToPackage, install } from 'supi'
import tape = require('tape')
import promisifyTape from 'tape-promise'
import { testDefaults } from '../utils'
const test = promisifyTape(tape)
test('install with --independent-leaves', async (t: tape.Test) => {
const project = prepareEmpty(t)
const manifest = await addDependenciesToPackage({}, ['pkg-with-1-dep@100.0.0'], await testDefaults({ independentLeaves: true }))
await project.has('pkg-with-1-dep')
await install(manifest, await testDefaults({ independentLeaves: true, preferFrozenLockfile: false }))
t.ok(isSubdir(path.resolve('node_modules'), await resolveLinkTarget(path.resolve('node_modules/pkg-with-1-dep'))), 'non-independent package is not symlinked directly from store')
})
test('--independent-leaves throws exception when executed on node_modules installed w/o the option', async (t: tape.Test) => {
const project = prepareEmpty(t)
const opts = await testDefaults({ independentLeaves: false })
const manifest = await addDependenciesToPackage({}, ['is-positive'], opts)
try {
await addDependenciesToPackage(manifest, ['is-negative'], {
...opts,
forceIndependentLeaves: true,
independentLeaves: true,
})
t.fail('installation should have failed')
} catch (err) {
t.equal(err['code'], 'ERR_PNPM_INDEPENDENT_LEAVES_NOT_WANTED') // tslint:disable-line:no-string-literal
t.ok(err.message.indexOf('This modules directory was created without the --independent-leaves option.') === 0)
}
// Install doesn't fail if independentLeaves is not forced
await addDependenciesToPackage(manifest, ['is-negative'], {
...opts,
forceIndependentLeaves: false,
independentLeaves: true,
})
await project.has('is-negative')
})
test('--no-independent-leaves throws exception when executed on node_modules installed with --independent-leaves', async (t: tape.Test) => {
prepareEmpty(t)
const manifest = await addDependenciesToPackage({}, ['is-positive'], await testDefaults({ independentLeaves: true }))
try {
await addDependenciesToPackage(manifest, ['is-negative'], await testDefaults({
forceIndependentLeaves: true,
independentLeaves: false,
}))
t.fail('installation should have failed')
} catch (err) {
t.equal(err['code'], 'ERR_PNPM_INDEPENDENT_LEAVES_WANTED') // tslint:disable-line:no-string-literal
t.ok(err.message.indexOf('This modules directory was created using the --independent-leaves option.') === 0)
}
})
// Covers https://github.com/pnpm/pnpm/issues/1547
test('installing with independent-leaves and hoistPattern', async (t) => {
const project = prepareEmpty(t)
await addDependenciesToPackage({}, ['pkg-with-1-dep@100.0.0'], await testDefaults({
hoistPattern: '*',
independentLeaves: true,
}))
await project.has('pkg-with-1-dep')
await project.has('.pnpm/node_modules/dep-of-pkg-with-1-dep')
// wrappy is linked directly from the store
await project.hasNot(`.pnpm/dep-of-pkg-with-1-dep@100.0.0`)
await project.storeHas('dep-of-pkg-with-1-dep', '100.0.0')
await project.has(`.pnpm/pkg-with-1-dep@100.0.0`)
})

View File

@@ -6,7 +6,6 @@ import './fromTarball'
import './frozenLockfile'
import './hoist'
import './hooks'
import './independentLeaves'
import './installationChecks'
import './lifecycleScripts'
import './local'

View File

@@ -282,28 +282,3 @@ test("don't unlink package that is not a link", async (t: tape.Test) => {
message: 'is-positive is not an external link',
}), 'reported warning')
})
test("don't unlink package that is not a link when independent-leaves = true", async (t: tape.Test) => {
prepareEmpty(t)
const reporter = sinon.spy()
const manifest = await addDependenciesToPackage({}, ['is-positive'], await testDefaults({ independentLeaves: true }))
await mutateModules(
[
{
dependencyNames: ['is-positive'],
manifest,
mutation: 'unlinkSome',
rootDir: process.cwd(),
},
],
await testDefaults({ independentLeaves: true, reporter })
)
t.ok(reporter.calledWithMatch({
level: 'warn',
message: 'is-positive is not an external link',
}), 'reported warning')
})

5
pnpm-lock.yaml generated
View File

@@ -1300,7 +1300,6 @@ importers:
'@pnpm/core-loggers': 'link:../core-loggers'
'@pnpm/fetcher-base': 'link:../fetcher-base'
'@pnpm/package-requester': 'link:../package-requester'
'@pnpm/pkgid-to-filename': 3.0.0
'@pnpm/resolver-base': 'link:../resolver-base'
'@pnpm/store-controller-types': 'link:../store-controller-types'
'@pnpm/types': 'link:../types'
@@ -1337,7 +1336,6 @@ importers:
'@pnpm/npm-resolver': 'workspace:*'
'@pnpm/package-requester': 'workspace:12.0.0-alpha.5'
'@pnpm/package-store': 'link:'
'@pnpm/pkgid-to-filename': 3.0.0
'@pnpm/resolver-base': 'workspace:7.0.1-alpha.0'
'@pnpm/store-controller-types': 'workspace:8.0.0-alpha.4'
'@pnpm/tarball-fetcher': 'workspace:*'
@@ -3862,7 +3860,6 @@ packages:
dependencies:
async-retry: 1.3.1
debug: 3.2.6
node-fetch: 2.6.0
dev: false
peerDependencies:
node-fetch: '*'
@@ -11928,7 +11925,6 @@ packages:
diff: 4.0.2
make-error: 1.3.6
source-map-support: 0.5.19
typescript: 3.9.3
yn: 3.1.1
dev: true
engines:
@@ -11978,7 +11974,6 @@ packages:
semver: 5.7.1
tslib: 1.13.0
tsutils: 2.29.0_typescript@3.9.3
typescript: 3.9.3
deprecated: 'TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.'
dev: true
engines: