mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-10 18:18:56 -04:00
fix: bins creation of direct deps
This commit is contained in:
5
.changeset/brave-radios-fetch.md
Normal file
5
.changeset/brave-radios-fetch.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/headless": patch
|
||||
---
|
||||
|
||||
bin files of dependencies linked from the workspace, should be created.
|
||||
6
.changeset/sweet-drinks-wash.md
Normal file
6
.changeset/sweet-drinks-wash.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/headless": patch
|
||||
"supi": patch
|
||||
---
|
||||
|
||||
Perform less filesystem operations during the creation of bin files of direct dependencies.
|
||||
@@ -44,7 +44,7 @@ import {
|
||||
} from '@pnpm/modules-yaml'
|
||||
import pkgIdToFilename from '@pnpm/pkgid-to-filename'
|
||||
import { fromDir as readPackageFromDir } from '@pnpm/read-package-json'
|
||||
import { readProjectManifestOnly } from '@pnpm/read-project-manifest'
|
||||
import { readProjectManifestOnly, safeReadProjectManifestOnly } from '@pnpm/read-project-manifest'
|
||||
import {
|
||||
PackageFilesResponse,
|
||||
StoreController,
|
||||
@@ -328,7 +328,26 @@ export default async (opts: HeadlessOptions) => {
|
||||
}
|
||||
|
||||
await linkAllBins(graph, { optional: opts.include.optionalDependencies, warn })
|
||||
await Promise.all(opts.projects.map(linkBinsOfImporter))
|
||||
await Promise.all(opts.projects.map(async (project) => {
|
||||
if (opts.publicHoistPattern?.length && path.relative(opts.lockfileDir, project.rootDir) === '') {
|
||||
await linkBinsOfImporter(project)
|
||||
} else {
|
||||
const directPkgDirs = Object.values(directDependenciesByImporterId[project.id])
|
||||
await linkBinsOfPackages(
|
||||
(
|
||||
await Promise.all(
|
||||
directPkgDirs.map(async (dir) => ({
|
||||
location: dir,
|
||||
manifest: await safeReadProjectManifestOnly(dir),
|
||||
}))
|
||||
)
|
||||
)
|
||||
.filter(({ manifest }) => manifest != null) as Array<{ location: string, manifest: DependencyManifest }>,
|
||||
project.binsDir,
|
||||
{ warn: (message: string) => logger.info({ message, prefix: project.rootDir }) }
|
||||
)
|
||||
}
|
||||
}))
|
||||
|
||||
if (currentLockfile && !R.equals(opts.projects.map(({ id }) => id).sort(), Object.keys(filteredLockfile.importers).sort())) {
|
||||
Object.assign(filteredLockfile.packages, currentLockfile.packages)
|
||||
@@ -570,7 +589,7 @@ async function lockfileToDepGraph (
|
||||
}
|
||||
|
||||
const peerDeps = pkgSnapshot.peerDependencies ? new Set(Object.keys(pkgSnapshot.peerDependencies)) : null
|
||||
graph[dir].children = await getChildrenPaths(ctx, allDeps, peerDeps)
|
||||
graph[dir].children = await getChildrenPaths(ctx, allDeps, peerDeps, '.')
|
||||
}
|
||||
for (const importerId of opts.importerIds) {
|
||||
const projectSnapshot = lockfile.importers[importerId]
|
||||
@@ -579,7 +598,7 @@ async function lockfileToDepGraph (
|
||||
...(opts.include.dependencies ? projectSnapshot.dependencies : {}),
|
||||
...(opts.include.optionalDependencies ? projectSnapshot.optionalDependencies : {}),
|
||||
}
|
||||
directDependenciesByImporterId[importerId] = await getChildrenPaths(ctx, rootDeps, null)
|
||||
directDependenciesByImporterId[importerId] = await getChildrenPaths(ctx, rootDeps, null, importerId)
|
||||
}
|
||||
}
|
||||
return { graph, directDependenciesByImporterId }
|
||||
@@ -599,13 +618,14 @@ async function getChildrenPaths (
|
||||
storeController: StoreController
|
||||
},
|
||||
allDeps: {[alias: string]: string},
|
||||
peerDeps: Set<string> | null
|
||||
peerDeps: Set<string> | null,
|
||||
importerId: string
|
||||
) {
|
||||
const children: {[alias: string]: string} = {}
|
||||
for (const alias of Object.keys(allDeps)) {
|
||||
const childDepPath = dp.refToAbsolute(allDeps[alias], alias, ctx.registries)
|
||||
if (childDepPath === null) {
|
||||
children[alias] = path.resolve(ctx.lockfileDir, allDeps[alias].substr(5))
|
||||
children[alias] = path.resolve(ctx.lockfileDir, importerId, allDeps[alias].substr(5))
|
||||
continue
|
||||
}
|
||||
const childRelDepPath = dp.refToRelative(allDeps[alias], alias) as string
|
||||
|
||||
@@ -761,7 +761,7 @@ test('installing with no symlinks', async (t) => {
|
||||
symlink: false,
|
||||
}))
|
||||
|
||||
t.deepEqual(await fs.readdir(path.join(prefix, 'node_modules')), ['.modules.yaml', '.pnpm'])
|
||||
t.deepEqual(await fs.readdir(path.join(prefix, 'node_modules')), ['.bin', '.modules.yaml', '.pnpm'])
|
||||
t.deepEqual(await fs.readdir(path.join(prefix, 'node_modules/.pnpm/rimraf@2.7.1/node_modules')), ['rimraf'])
|
||||
|
||||
const project = assertProject(t, prefix)
|
||||
|
||||
@@ -14,7 +14,7 @@ import headless from '@pnpm/headless'
|
||||
import {
|
||||
runLifecycleHooksConcurrently,
|
||||
} from '@pnpm/lifecycle'
|
||||
import linkBins from '@pnpm/link-bins'
|
||||
import linkBins, { linkBinsOfPackages } from '@pnpm/link-bins'
|
||||
import {
|
||||
ProjectSnapshot,
|
||||
writeCurrentLockfile,
|
||||
@@ -25,11 +25,11 @@ import logger, { streamParser } from '@pnpm/logger'
|
||||
import { getAllDependenciesFromManifest } from '@pnpm/manifest-utils'
|
||||
import { write as writeModulesYaml } from '@pnpm/modules-yaml'
|
||||
import readModulesDirs from '@pnpm/read-modules-dir'
|
||||
import { safeReadProjectManifestOnly } from '@pnpm/read-project-manifest'
|
||||
import { removeBin } from '@pnpm/remove-bins'
|
||||
import resolveDependencies, {
|
||||
DependenciesGraph,
|
||||
DependenciesGraphNode,
|
||||
ImporterToResolve,
|
||||
} from '@pnpm/resolve-dependencies'
|
||||
import {
|
||||
PreferredVersions,
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
} from '@pnpm/resolver-base'
|
||||
import {
|
||||
DependenciesField,
|
||||
DependencyManifest,
|
||||
ProjectManifest,
|
||||
} from '@pnpm/types'
|
||||
import parseWantedDependencies from '../parseWantedDependencies'
|
||||
@@ -712,16 +713,47 @@ async function installInContext (
|
||||
})
|
||||
}
|
||||
|
||||
const binWarn = (prefix: string, message: string) => logger.info({ message, prefix })
|
||||
if (result.newDepPaths?.length) {
|
||||
const newPkgs = R.props<string, DependenciesGraphNode>(result.newDepPaths, dependenciesGraph)
|
||||
await linkAllBins(newPkgs, dependenciesGraph, {
|
||||
optional: opts.include.optionalDependencies,
|
||||
warn: (message: string) => logger.warn({ message, prefix: opts.lockfileDir }),
|
||||
warn: binWarn.bind(null, opts.lockfileDir),
|
||||
})
|
||||
}
|
||||
|
||||
await Promise.all(projectsToResolve.map(async (project, index) => {
|
||||
const linkedPackages = await linkBinsOfImporter(project)
|
||||
let linkedPackages!: string[]
|
||||
if (ctx.publicHoistPattern?.length && path.relative(project.rootDir, opts.lockfileDir) === '') {
|
||||
linkedPackages = await linkBins(project.modulesDir, project.binsDir, {
|
||||
allowExoticManifests: true,
|
||||
warn: binWarn.bind(null, project.rootDir),
|
||||
})
|
||||
} else {
|
||||
const directPkgs = [
|
||||
...R.props<string, DependenciesGraphNode>(
|
||||
Object.values(dependenciesByProjectId[project.id]).filter((depPath) => !ctx.skipped.has(depPath)),
|
||||
dependenciesGraph
|
||||
),
|
||||
...linkedDependenciesByProjectId[project.id].map(({ pkgId }) => ({
|
||||
dir: path.join(project.rootDir, pkgId.substring(5)),
|
||||
fetchingBundledManifest: undefined,
|
||||
})),
|
||||
]
|
||||
linkedPackages = await linkBinsOfPackages(
|
||||
(
|
||||
await Promise.all(
|
||||
directPkgs.map(async (dep) => ({
|
||||
location: dep.dir,
|
||||
manifest: await dep.fetchingBundledManifest?.() ?? await safeReadProjectManifestOnly(dep.dir),
|
||||
}))
|
||||
)
|
||||
)
|
||||
.filter(({ manifest }) => manifest != null) as Array<{ location: string, manifest: DependencyManifest }>,
|
||||
project.binsDir,
|
||||
{ warn: binWarn.bind(null, project.rootDir) }
|
||||
)
|
||||
}
|
||||
const projectToInstall = projects[index]
|
||||
if (opts.global && projectToInstall.mutation.includes('install')) {
|
||||
projectToInstall.wantedDependencies.forEach(pkg => {
|
||||
@@ -846,12 +878,7 @@ function prefIsLocalTarball (pref: string) {
|
||||
|
||||
const limitLinking = pLimit(16)
|
||||
|
||||
function linkBinsOfImporter ({ modulesDir, binsDir, rootDir }: ImporterToResolve) {
|
||||
const warn = (message: string) => logger.info({ message, prefix: rootDir })
|
||||
return linkBins(modulesDir, binsDir, { allowExoticManifests: true, warn })
|
||||
}
|
||||
|
||||
function linkAllBins (
|
||||
async function linkAllBins (
|
||||
depNodes: DependenciesGraphNode[],
|
||||
depGraph: DependenciesGraph,
|
||||
opts: {
|
||||
@@ -859,7 +886,7 @@ function linkAllBins (
|
||||
warn: (message: string) => void
|
||||
}
|
||||
) {
|
||||
return Promise.all(
|
||||
return R.unnest(await Promise.all(
|
||||
depNodes.map(depNode => limitLinking(() => linkBinsOfDependencies(depNode, depGraph, opts)))
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1237,10 +1237,10 @@ test('installing with no symlinks', async (t) => {
|
||||
version: '0.0.0',
|
||||
},
|
||||
['rimraf@2.7.1'],
|
||||
await testDefaults({ symlink: false })
|
||||
await testDefaults({ fastUnpack: false, symlink: false })
|
||||
)
|
||||
|
||||
t.deepEqual(await fs.readdir(path.resolve('node_modules')), ['.modules.yaml', '.pnpm'])
|
||||
t.deepEqual(await fs.readdir(path.resolve('node_modules')), ['.bin', '.modules.yaml', '.pnpm'])
|
||||
t.deepEqual(await fs.readdir(path.resolve('node_modules/.pnpm/rimraf@2.7.1/node_modules')), ['rimraf'])
|
||||
|
||||
t.ok(await project.readCurrentLockfile())
|
||||
|
||||
Reference in New Issue
Block a user