fix: bins creation of direct deps

This commit is contained in:
Zoltan Kochan
2020-10-03 20:30:23 +03:00
parent 2762781ccf
commit fb92e9f887
6 changed files with 79 additions and 21 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/headless": patch
---
bin files of dependencies linked from the workspace, should be created.

View File

@@ -0,0 +1,6 @@
---
"@pnpm/headless": patch
"supi": patch
---
Perform less filesystem operations during the creation of bin files of direct dependencies.

View File

@@ -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

View File

@@ -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)

View File

@@ -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)))
)
))
}

View File

@@ -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())