diff --git a/.changeset/old-cars-notice.md b/.changeset/old-cars-notice.md new file mode 100644 index 00000000000..9dd95d04eb9 --- /dev/null +++ b/.changeset/old-cars-notice.md @@ -0,0 +1,37 @@ +--- +"@pnpm/dependency-path": major +"@pnpm/plugin-commands-installation": minor +"@pnpm/plugin-commands-publishing": minor +"@pnpm/plugin-commands-script-runners": minor +"@pnpm/plugin-commands-licenses": minor +"@pnpm/plugin-commands-outdated": minor +"@pnpm/plugin-commands-patching": minor +"@pnpm/read-projects-context": minor +"@pnpm/plugin-commands-listing": minor +"@pnpm/resolve-dependencies": minor +"@pnpm/plugin-commands-deploy": minor +"@pnpm/reviewing.dependencies-hierarchy": minor +"@pnpm/plugin-commands-audit": minor +"@pnpm/store-connection-manager": minor +"@pnpm/package-requester": minor +"@pnpm/plugin-commands-rebuild": minor +"@pnpm/modules-cleaner": minor +"@pnpm/plugin-commands-store": minor +"@pnpm/license-scanner": minor +"@pnpm/lockfile-to-pnp": minor +"@pnpm/modules-yaml": minor +"@pnpm/lockfile-utils": minor +"@pnpm/get-context": minor +"@pnpm/mount-modules": minor +"@pnpm/headless": minor +"@pnpm/package-store": minor +"@pnpm/deps.graph-builder": minor +"@pnpm/hoist": minor +"@pnpm/core": minor +"@pnpm/audit": minor +"@pnpm/list": minor +"@pnpm/config": minor +"@pnpm/server": minor +--- + +New setting called `virtual-store-dir-max-length` added for modifying the max allowed length of the directories inside `node_modules/.pnpm`. The default length is 120 characters [#7355](https://github.com/pnpm/pnpm/issues/7355). diff --git a/config/config/src/Config.ts b/config/config/src/Config.ts index 05dd981ea7c..55276b68948 100644 --- a/config/config/src/Config.ts +++ b/config/config/src/Config.ts @@ -192,6 +192,7 @@ export interface Config { dedupeInjectedDeps?: boolean nodeOptions?: string packageManagerStrict?: boolean + virtualStoreDirMaxLength: number } export interface ConfigWithDeprecatedSettings extends Config { diff --git a/config/config/src/index.ts b/config/config/src/index.ts index 7d16294c5c2..e1346f4dc88 100644 --- a/config/config/src/index.ts +++ b/config/config/src/index.ts @@ -140,6 +140,7 @@ export const types = Object.assign({ 'use-stderr': Boolean, 'verify-store-integrity': Boolean, 'virtual-store-dir': String, + 'virtual-store-dir-max-length': Number, 'workspace-concurrency': Number, 'workspace-packages': [String, Array], 'workspace-root': Boolean, @@ -272,6 +273,7 @@ export async function getConfig ( 'workspace-prefix': opts.workspaceDir, 'embed-readme': false, 'registry-supports-time-field': false, + 'virtual-store-dir-max-length': 120, } const { config: npmConfig, warnings, failedToLoadBuiltInConfig } = loadNpmConf(cliOptions, rcOptionsTypes, defaultOptions) diff --git a/deps/graph-builder/src/lockfileToDepGraph.ts b/deps/graph-builder/src/lockfileToDepGraph.ts index 4abb334c7bb..d61a7185a90 100644 --- a/deps/graph-builder/src/lockfileToDepGraph.ts +++ b/deps/graph-builder/src/lockfileToDepGraph.ts @@ -68,6 +68,7 @@ export interface LockfileToDepGraphOptions { storeDir: string virtualStoreDir: string supportedArchitectures?: SupportedArchitectures + virtualStoreDirMaxLength: number } export interface DirectDependenciesByImporterId { @@ -103,7 +104,7 @@ export async function lockfileToDepGraph ( if (opts.skipped.has(depPath)) return // TODO: optimize. This info can be already returned by pkgSnapshotToResolution() const { name: pkgName, version: pkgVersion } = nameVerFromPkgSnapshot(depPath, pkgSnapshot) - const modules = path.join(opts.virtualStoreDir, dp.depPathToFilename(depPath), 'node_modules') + const modules = path.join(opts.virtualStoreDir, dp.depPathToFilename(depPath, opts.virtualStoreDirMaxLength), 'node_modules') const packageId = packageIdFromSnapshot(depPath, pkgSnapshot) const pkg = { @@ -208,6 +209,7 @@ export async function lockfileToDepGraph ( storeController: opts.storeController, storeDir: opts.storeDir, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, } for (const [dir, node] of Object.entries(graph)) { const pkgSnapshot = pkgSnapshotByLocation[dir] @@ -244,6 +246,7 @@ function getChildrenPaths ( lockfileDir: string sideEffectsCacheRead: boolean storeController: StoreController + virtualStoreDirMaxLength: number }, allDeps: { [alias: string]: string }, peerDeps: Set | null, @@ -263,7 +266,7 @@ function getChildrenPaths ( } else if (childPkgSnapshot) { if (ctx.skipped.has(childRelDepPath)) continue const pkgName = nameVerFromPkgSnapshot(childRelDepPath, childPkgSnapshot).name - children[alias] = path.join(ctx.virtualStoreDir, dp.depPathToFilename(childRelDepPath), 'node_modules', pkgName) + children[alias] = path.join(ctx.virtualStoreDir, dp.depPathToFilename(childRelDepPath, ctx.virtualStoreDirMaxLength), 'node_modules', pkgName) } else if (ref.indexOf('file:') === 0) { children[alias] = path.resolve(ctx.lockfileDir, ref.slice(5)) } else if (!ctx.skipped.has(childRelDepPath) && ((peerDeps == null) || !peerDeps.has(alias))) { diff --git a/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts b/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts index ff47a7bdc97..c544e08dcd7 100644 --- a/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts +++ b/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts @@ -47,6 +47,7 @@ export type StrictRebuildOptions = { deployAllFiles: boolean neverBuiltDependencies?: string[] onlyBuiltDependencies?: string[] + virtualStoreDirMaxLength: number } & Pick export type RebuildOptions = Partial & diff --git a/exec/plugin-commands-rebuild/src/implementation/index.ts b/exec/plugin-commands-rebuild/src/implementation/index.ts index 7e63efd2f2e..ba34200ff4c 100644 --- a/exec/plugin-commands-rebuild/src/implementation/index.ts +++ b/exec/plugin-commands-rebuild/src/implementation/index.ts @@ -200,6 +200,7 @@ export async function rebuildProjects ( skipped: Array.from(ctx.skipped), storeDir: ctx.storeDir, virtualStoreDir: ctx.virtualStoreDir, + virtualStoreDirMaxLength: ctx.virtualStoreDirMaxLength, }) } @@ -295,7 +296,7 @@ async function _rebuild ( const pkgInfo = nameVerFromPkgSnapshot(depPath, pkgSnapshot) const pkgRoots = opts.nodeLinker === 'hoisted' ? (ctx.modulesFile?.hoistedLocations?.[depPath] ?? []).map((hoistedLocation) => path.join(opts.lockfileDir, hoistedLocation)) - : [path.join(ctx.virtualStoreDir, dp.depPathToFilename(depPath), 'node_modules', pkgInfo.name)] + : [path.join(ctx.virtualStoreDir, dp.depPathToFilename(depPath, opts.virtualStoreDirMaxLength), 'node_modules', pkgInfo.name)] if (pkgRoots.length === 0) { if (pkgSnapshot.optional) return throw new PnpmError('MISSING_HOISTED_LOCATIONS', `${depPath} is not found in hoistedLocations inside node_modules/.modules.yaml`, { @@ -306,7 +307,7 @@ async function _rebuild ( try { const extraBinPaths = ctx.extraBinPaths if (opts.nodeLinker !== 'hoisted') { - const modules = path.join(ctx.virtualStoreDir, dp.depPathToFilename(depPath), 'node_modules') + const modules = path.join(ctx.virtualStoreDir, dp.depPathToFilename(depPath, opts.virtualStoreDirMaxLength), 'node_modules') const binPath = path.join(pkgRoot, 'node_modules', '.bin') await linkBins(modules, binPath, { extraNodePaths: ctx.extraNodePaths, warn }) } else { @@ -403,7 +404,7 @@ async function _rebuild ( .map(async (depPath) => limitLinking(async () => { const pkgSnapshot = pkgSnapshots[depPath] const pkgInfo = nameVerFromPkgSnapshot(depPath, pkgSnapshot) - const modules = path.join(ctx.virtualStoreDir, dp.depPathToFilename(depPath), 'node_modules') + const modules = path.join(ctx.virtualStoreDir, dp.depPathToFilename(depPath, opts.virtualStoreDirMaxLength), 'node_modules') const binPath = path.join(modules, pkgInfo.name, 'node_modules', '.bin') return linkBins(modules, binPath, { warn }) })) diff --git a/exec/plugin-commands-rebuild/test/utils/index.ts b/exec/plugin-commands-rebuild/test/utils/index.ts index c62c446e97b..57c43cb49d8 100644 --- a/exec/plugin-commands-rebuild/test/utils/index.ts +++ b/exec/plugin-commands-rebuild/test/utils/index.ts @@ -52,4 +52,5 @@ export const DEFAULT_OPTS = { cpu: ['current'], libc: ['current'], }, + virtualStoreDirMaxLength: 120, } diff --git a/exec/plugin-commands-script-runners/test/utils/index.ts b/exec/plugin-commands-script-runners/test/utils/index.ts index a6920b39bd9..257971a5aaa 100644 --- a/exec/plugin-commands-script-runners/test/utils/index.ts +++ b/exec/plugin-commands-script-runners/test/utils/index.ts @@ -55,6 +55,7 @@ export const DEFAULT_OPTS = { cpu: ['current'], libc: ['current'], }, + virtualStoreDirMaxLength: 120, } export const DLX_DEFAULT_OPTS = { @@ -91,4 +92,5 @@ export const DLX_DEFAULT_OPTS = { cpu: ['current'], libc: ['current'], }, + virtualStoreDirMaxLength: 120, } diff --git a/lockfile/audit/src/index.ts b/lockfile/audit/src/index.ts index 98b774631f2..b819e0ac407 100644 --- a/lockfile/audit/src/index.ts +++ b/lockfile/audit/src/index.ts @@ -23,6 +23,7 @@ export async function audit ( registry: string retry?: RetryTimeoutOptions timeout?: number + virtualStoreDirMaxLength: number } ): Promise { const auditTree = await lockfileToAuditTree(lockfile, { include: opts.include, lockfileDir: opts.lockfileDir }) @@ -55,6 +56,7 @@ export async function audit ( lockfile, lockfileDir: opts.lockfileDir, include: opts.include, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }) } catch (err: unknown) { assert(util.types.isNativeError(err)) @@ -79,6 +81,7 @@ async function extendWithDependencyPaths (auditReport: AuditReport, opts: { lockfile: Lockfile lockfileDir: string include?: { [dependenciesField in DependenciesField]: boolean } + virtualStoreDirMaxLength: number }): Promise { const { advisories } = auditReport if (!Object.keys(advisories).length) return auditReport @@ -88,6 +91,7 @@ async function extendWithDependencyPaths (auditReport: AuditReport, opts: { lockfileDir: opts.lockfileDir, depth: Infinity, include: opts.include, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, } const _searchPackagePaths = searchPackagePaths.bind(null, searchOpts, projectDirs) // eslint-disable-next-line @typescript-eslint/naming-convention @@ -104,6 +108,7 @@ async function searchPackagePaths ( lockfileDir: string depth: number include?: { [dependenciesField in DependenciesField]: boolean } + virtualStoreDirMaxLength: number }, projectDirs: string[], pkg: string diff --git a/lockfile/audit/test/index.ts b/lockfile/audit/test/index.ts index df0762623e5..33e9933de69 100644 --- a/lockfile/audit/test/index.ts +++ b/lockfile/audit/test/index.ts @@ -164,6 +164,7 @@ describe('audit', () => { retry: { retries: 0, }, + virtualStoreDirMaxLength: 120, }) } catch (_err: any) { // eslint-disable-line err = _err diff --git a/lockfile/lockfile-to-pnp/src/index.ts b/lockfile/lockfile-to-pnp/src/index.ts index 39cc748f50b..695c8a92224 100644 --- a/lockfile/lockfile-to-pnp/src/index.ts +++ b/lockfile/lockfile-to-pnp/src/index.ts @@ -15,6 +15,7 @@ export async function writePnpFile ( importerNames: Record lockfileDir: string virtualStoreDir: string + virtualStoreDirMaxLength: number registries: Registries } ): Promise { @@ -36,6 +37,7 @@ export function lockfileToPackageRegistry ( importerNames: { [importerId: string]: string } lockfileDir: string virtualStoreDir: string + virtualStoreDirMaxLength: number registries: Registries } ): PackageRegistry { @@ -87,7 +89,7 @@ export function lockfileToPackageRegistry ( // Seems like this field should always contain a relative path let packageLocation = normalizePath(path.relative(opts.lockfileDir, path.join( opts.virtualStoreDir, - depPathToFilename(relDepPath), + depPathToFilename(relDepPath, opts.virtualStoreDirMaxLength), 'node_modules', name ))) diff --git a/lockfile/lockfile-to-pnp/test/index.ts b/lockfile/lockfile-to-pnp/test/index.ts index bb29c03aa11..05a599dda73 100644 --- a/lockfile/lockfile-to-pnp/test/index.ts +++ b/lockfile/lockfile-to-pnp/test/index.ts @@ -61,6 +61,7 @@ test('lockfileToPackageRegistry', () => { default: 'https://registry.npmjs.org/', }, virtualStoreDir: path.resolve('node_modules/.pnpm'), + virtualStoreDirMaxLength: 120, }) const actual = Array.from( @@ -212,6 +213,7 @@ test('lockfileToPackageRegistry packages that have peer deps', () => { default: 'https://registry.npmjs.org/', }, virtualStoreDir: path.resolve('node_modules/.pnpm'), + virtualStoreDirMaxLength: 120, }) const actual = Array.from( diff --git a/lockfile/lockfile-utils/src/extendProjectsWithTargetDirs.ts b/lockfile/lockfile-utils/src/extendProjectsWithTargetDirs.ts index 5acffc80dcd..3ae5676d323 100644 --- a/lockfile/lockfile-utils/src/extendProjectsWithTargetDirs.ts +++ b/lockfile/lockfile-utils/src/extendProjectsWithTargetDirs.ts @@ -12,11 +12,12 @@ export function extendProjectsWithTargetDirs ( ctx: { virtualStoreDir: string pkgLocationsByDepPath?: Record + virtualStoreDirMaxLength: number } ): Array { const getLocalLocations: GetLocalLocations = ctx.pkgLocationsByDepPath != null ? (depPath: string) => ctx.pkgLocationsByDepPath![depPath] - : (depPath: string, pkgName: string) => [path.join(ctx.virtualStoreDir, depPathToFilename(depPath), 'node_modules', pkgName)] + : (depPath: string, pkgName: string) => [path.join(ctx.virtualStoreDir, depPathToFilename(depPath, ctx.virtualStoreDirMaxLength), 'node_modules', pkgName)] const projectsById: Record = Object.fromEntries(projects.map((project) => [project.id, { ...project, targetDirs: [] as string[] }])) Object.entries(lockfile.packages ?? {}) diff --git a/lockfile/plugin-commands-audit/src/audit.ts b/lockfile/plugin-commands-audit/src/audit.ts index b5ac3cf9bb7..1f078e48a2f 100644 --- a/lockfile/plugin-commands-audit/src/audit.ts +++ b/lockfile/plugin-commands-audit/src/audit.ts @@ -141,6 +141,7 @@ export async function handler ( | 'userConfig' | 'rawConfig' | 'rootProjectManifest' + | 'virtualStoreDirMaxLength' > ): Promise<{ exitCode: number, output: string }> { const lockfileDir = opts.lockfileDir ?? opts.dir @@ -179,6 +180,7 @@ export async function handler ( retries: opts.fetchRetries, }, timeout: opts.fetchTimeout, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }) } catch (err: any) { // eslint-disable-line if (opts.ignoreRegistryErrors) { diff --git a/lockfile/plugin-commands-audit/test/fix.ts b/lockfile/plugin-commands-audit/test/fix.ts index 652775088d4..05ae9f9a802 100644 --- a/lockfile/plugin-commands-audit/test/fix.ts +++ b/lockfile/plugin-commands-audit/test/fix.ts @@ -29,6 +29,7 @@ test('overrides are added for vulnerable dependencies', async () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(0) @@ -53,6 +54,7 @@ test('no overrides are added if no vulnerabilities are found', async () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(0) @@ -88,6 +90,7 @@ test('CVEs found in the allow list are not added as overrides', async () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(0) expect(output).toMatch(/Run "pnpm install"/) diff --git a/lockfile/plugin-commands-audit/test/index.ts b/lockfile/plugin-commands-audit/test/index.ts index a5f1775c75a..04bff811f89 100644 --- a/lockfile/plugin-commands-audit/test/index.ts +++ b/lockfile/plugin-commands-audit/test/index.ts @@ -60,6 +60,7 @@ export const DEFAULT_OPTS = { useRunningStoreServer: false, useStoreServer: false, workspaceConcurrency: 4, + virtualStoreDirMaxLength: 120, } describe('plugin-commands-audit', () => { @@ -80,6 +81,7 @@ describe('plugin-commands-audit', () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(1) expect(stripAnsi(output)).toMatchSnapshot() @@ -97,6 +99,7 @@ describe('plugin-commands-audit', () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(1) @@ -114,6 +117,7 @@ describe('plugin-commands-audit', () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(1) @@ -130,6 +134,7 @@ describe('plugin-commands-audit', () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, }) expect(stripAnsi(output)).toBe('No known vulnerabilities found\n') @@ -147,6 +152,7 @@ describe('plugin-commands-audit', () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, }) const json = JSON.parse(output) @@ -166,6 +172,7 @@ describe('plugin-commands-audit', () => { rawConfig, dev: true, registries, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(0) @@ -186,6 +193,7 @@ describe('plugin-commands-audit', () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(0) @@ -207,6 +215,7 @@ describe('plugin-commands-audit', () => { [`${registries.default.replace(/^https?:/, '')}:_authToken`]: '123', }, registries, + virtualStoreDirMaxLength: 120, }) expect(stripAnsi(output)).toBe('No known vulnerabilities found\n') @@ -227,6 +236,7 @@ describe('plugin-commands-audit', () => { userConfig: {}, rawConfig, registries, + virtualStoreDirMaxLength: 120, })).rejects.toThrow(AuditEndpointNotExistsError) }) @@ -255,6 +265,7 @@ describe('plugin-commands-audit', () => { }, }, }, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(1) @@ -287,6 +298,7 @@ describe('plugin-commands-audit', () => { }, }, }, + virtualStoreDirMaxLength: 120, }) expect(exitCode).toBe(1) diff --git a/modules-mounter/daemon/src/makeVirtualNodeModules.ts b/modules-mounter/daemon/src/makeVirtualNodeModules.ts index edc7807c57e..b1b84260f9f 100644 --- a/modules-mounter/daemon/src/makeVirtualNodeModules.ts +++ b/modules-mounter/daemon/src/makeVirtualNodeModules.ts @@ -29,7 +29,7 @@ export function makeVirtualNodeModules (lockfile: Lockfile): DirEntry { for (const [depName, ref] of Object.entries(lockfile.importers['.'][depType] ?? {})) { const symlink: DirEntry = { entryType: 'symlink', - target: `./.pnpm/${dp.depPathToFilename(dp.refToRelative(ref, depName)!)}/node_modules/${depName}`, + target: `./.pnpm/${dp.depPathToFilename(dp.refToRelative(ref, depName)!, 120)}/node_modules/${depName}`, } addDirEntry(entries, depName, symlink) } @@ -45,7 +45,7 @@ function createVirtualStoreDir (lockfile: Lockfile): Record { for (const [depPath, pkgSnapshot] of Object.entries(lockfile.packages ?? {})) { const { name } = nameVerFromPkgSnapshot(depPath, pkgSnapshot) const pkgNodeModules = {} as Record - const currentPath = dp.depPathToFilename(depPath) + const currentPath = dp.depPathToFilename(depPath, 120) const pkgDir: DirEntry = { entryType: 'index', depPath, @@ -54,7 +54,7 @@ function createVirtualStoreDir (lockfile: Lockfile): Record { for (const [depName, ref] of Object.entries({ ...pkgSnapshot.dependencies, ...pkgSnapshot.optionalDependencies })) { const symlink: DirEntry = { entryType: 'symlink', - target: normalize(path.relative(`${currentPath}/node_modules/`, `${dp.depPathToFilename(dp.refToRelative(ref, depName)!)}/node_modules/${depName}`)), + target: normalize(path.relative(`${currentPath}/node_modules/`, `${dp.depPathToFilename(dp.refToRelative(ref, depName)!, 120)}/node_modules/${depName}`)), } addDirEntry(pkgNodeModules, depName, symlink) } diff --git a/packages/dependency-path/src/index.ts b/packages/dependency-path/src/index.ts index cf768bbcf0e..1e07449153c 100644 --- a/packages/dependency-path/src/index.ts +++ b/packages/dependency-path/src/index.ts @@ -128,17 +128,15 @@ export function parse (dependencyPath: string): DependencyPath { return {} } -const MAX_LENGTH_WITHOUT_HASH = 120 - 26 - 1 - -export function depPathToFilename (depPath: string): string { +export function depPathToFilename (depPath: string, maxLengthWithoutHash: number): string { let filename = depPathToFilenameUnescaped(depPath).replace(/[\\/:*?"<>|]/g, '+') if (filename.includes('(')) { filename = filename .replace(/\)$/, '') .replace(/(\)\()|\(|\)/g, '_') } - if (filename.length > 120 || filename !== filename.toLowerCase() && !filename.startsWith('file+')) { - return `${filename.substring(0, MAX_LENGTH_WITHOUT_HASH)}_${createBase32Hash(filename)}` + if (filename.length > maxLengthWithoutHash || filename !== filename.toLowerCase() && !filename.startsWith('file+')) { + return `${filename.substring(0, maxLengthWithoutHash - 27)}_${createBase32Hash(filename)}` } return filename } diff --git a/packages/dependency-path/test/index.ts b/packages/dependency-path/test/index.ts index ad39836750d..aa5fa69fd29 100644 --- a/packages/dependency-path/test/index.ts +++ b/packages/dependency-path/test/index.ts @@ -71,19 +71,19 @@ test('refToRelative()', () => { }) test('depPathToFilename()', () => { - expect(depPathToFilename('/foo@1.0.0')).toBe('foo@1.0.0') - expect(depPathToFilename('/@foo/bar@1.0.0')).toBe('@foo+bar@1.0.0') - expect(depPathToFilename('github.com/something/foo/0000?v=1')).toBe('github.com+something+foo+0000+v=1') - expect(depPathToFilename('\\//:*?"<>|')).toBe('++++++++++') - expect(depPathToFilename('/foo@1.0.0(react@16.0.0)(react-dom@16.0.0)')).toBe('foo@1.0.0_react@16.0.0_react-dom@16.0.0') - expect(depPathToFilename('/foo@1.0.0(react@16.0.0(react-dom@1.0.0))(react-dom@16.0.0)')).toBe('foo@1.0.0_react@16.0.0_react-dom@1.0.0__react-dom@16.0.0') + expect(depPathToFilename('/foo@1.0.0', 120)).toBe('foo@1.0.0') + expect(depPathToFilename('/@foo/bar@1.0.0', 120)).toBe('@foo+bar@1.0.0') + expect(depPathToFilename('github.com/something/foo/0000?v=1', 120)).toBe('github.com+something+foo+0000+v=1') + expect(depPathToFilename('\\//:*?"<>|', 120)).toBe('++++++++++') + expect(depPathToFilename('/foo@1.0.0(react@16.0.0)(react-dom@16.0.0)', 120)).toBe('foo@1.0.0_react@16.0.0_react-dom@16.0.0') + expect(depPathToFilename('/foo@1.0.0(react@16.0.0(react-dom@1.0.0))(react-dom@16.0.0)', 120)).toBe('foo@1.0.0_react@16.0.0_react-dom@1.0.0__react-dom@16.0.0') - const filename = depPathToFilename('file:test/foo-1.0.0.tgz_foo@2.0.0') + const filename = depPathToFilename('file:test/foo-1.0.0.tgz_foo@2.0.0', 120) expect(filename).toBe('file+test+foo-1.0.0.tgz_foo@2.0.0') expect(filename).not.toContain(':') - expect(depPathToFilename('abcd/'.repeat(200))).toBe('abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abc_jvx2blbax4cyhfgrgozfgpdv24') // cspell:disable-line - expect(depPathToFilename('/JSONSteam@1.0.0')).toBe('JSONSteam@1.0.0_jmswpk4sf667aelr6wp2xd3p54') // cspell:disable-line + expect(depPathToFilename('abcd/'.repeat(200), 120)).toBe('abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abc_jvx2blbax4cyhfgrgozfgpdv24') // cspell:disable-line + expect(depPathToFilename('/JSONSteam@1.0.0', 120)).toBe('JSONSteam@1.0.0_jmswpk4sf667aelr6wp2xd3p54') // cspell:disable-line }) test('tryGetPackageId', () => { diff --git a/patching/plugin-commands-patching/test/patch.test.ts b/patching/plugin-commands-patching/test/patch.test.ts index dbf4e76107b..1e1b101d758 100644 --- a/patching/plugin-commands-patching/test/patch.test.ts +++ b/patching/plugin-commands-patching/test/patch.test.ts @@ -27,6 +27,7 @@ const basePatchOption = { registries: { default: `http://localhost:${REGISTRY_MOCK_PORT}/` }, userConfig: {}, virtualStoreDir: 'node_modules/.pnpm', + virtualStoreDirMaxLength: 120, } describe('patch and commit', () => { diff --git a/patching/plugin-commands-patching/test/utils/index.ts b/patching/plugin-commands-patching/test/utils/index.ts index f9c76366222..fee6aa73997 100644 --- a/patching/plugin-commands-patching/test/utils/index.ts +++ b/patching/plugin-commands-patching/test/utils/index.ts @@ -53,4 +53,5 @@ export const DEFAULT_OPTS = { cpu: ['current'], libc: ['current'], }, + virtualStoreDirMaxLength: 120, } diff --git a/pkg-manager/core/src/getPeerDependencyIssues.ts b/pkg-manager/core/src/getPeerDependencyIssues.ts index 61c6f47dfca..ea3c0222bc3 100644 --- a/pkg-manager/core/src/getPeerDependencyIssues.ts +++ b/pkg-manager/core/src/getPeerDependencyIssues.ts @@ -24,6 +24,7 @@ export type ListMissingPeersOptions = Partial > & Partial> & Pick +& Required> export async function getPeerDependencyIssues ( projects: ProjectOptions[], @@ -86,6 +87,7 @@ export async function getPeerDependencyIssues ( storeController: opts.storeController, tag: 'latest', virtualStoreDir: ctx.virtualStoreDir, + virtualStoreDirMaxLength: ctx.virtualStoreDirMaxLength, wantedLockfile: ctx.wantedLockfile, workspacePackages: opts.workspacePackages ?? {}, supportedArchitectures: opts.supportedArchitectures, diff --git a/pkg-manager/core/src/install/extendInstallOptions.ts b/pkg-manager/core/src/install/extendInstallOptions.ts index a3f980be4b8..b24b8fc2475 100644 --- a/pkg-manager/core/src/install/extendInstallOptions.ts +++ b/pkg-manager/core/src/install/extendInstallOptions.ts @@ -144,6 +144,7 @@ export interface StrictInstallOptions { supportedArchitectures?: SupportedArchitectures hoistWorkspacePackages?: boolean + virtualStoreDirMaxLength: number } export type InstallOptions = @@ -237,6 +238,7 @@ const defaults = (opts: InstallOptions): StrictInstallOptions => { ignoreWorkspaceCycles: false, disallowWorkspaceCycles: false, excludeLinksFromLockfile: false, + virtualStoreDirMaxLength: 120, } as StrictInstallOptions } diff --git a/pkg-manager/core/src/install/index.ts b/pkg-manager/core/src/install/index.ts index 9444de69c0e..60d9ff7369e 100644 --- a/pkg-manager/core/src/install/index.ts +++ b/pkg-manager/core/src/install/index.ts @@ -1051,6 +1051,7 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => { tag: opts.tag, updateToLatest: opts.updateToLatest, virtualStoreDir: ctx.virtualStoreDir, + virtualStoreDirMaxLength: ctx.virtualStoreDirMaxLength, wantedLockfile: ctx.wantedLockfile, workspacePackages: opts.workspacePackages, patchedDependencies: opts.patchedDependencies, @@ -1134,6 +1135,7 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => { skipped: ctx.skipped, storeController: opts.storeController, virtualStoreDir: ctx.virtualStoreDir, + virtualStoreDirMaxLength: ctx.virtualStoreDirMaxLength, wantedLockfile: newLockfile, wantedToBeSkippedPackageIds, hoistWorkspacePackages: opts.hoistWorkspacePackages, @@ -1148,6 +1150,7 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => { importerNames, lockfileDir: ctx.lockfileDir, virtualStoreDir: ctx.virtualStoreDir, + virtualStoreDirMaxLength: ctx.virtualStoreDirMaxLength, registries: ctx.registries, }) } @@ -1276,7 +1279,10 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => { } })) - const projectsWithTargetDirs = extendProjectsWithTargetDirs(projects, newLockfile, ctx) + const projectsWithTargetDirs = extendProjectsWithTargetDirs(projects, newLockfile, { + virtualStoreDir: ctx.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, + }) await Promise.all([ opts.useLockfile && opts.saveLockfile ? writeLockfiles({ @@ -1315,6 +1321,7 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => { skipped: Array.from(ctx.skipped), storeDir: ctx.storeDir, virtualStoreDir: ctx.virtualStoreDir, + virtualStoreDirMaxLength: ctx.virtualStoreDirMaxLength, }, { makeModulesDir: Object.keys(result.currentLockfile.packages ?? {}).length > 0, }) diff --git a/pkg-manager/core/src/install/link.ts b/pkg-manager/core/src/install/link.ts index 4d5feab0932..6bba58ce519 100644 --- a/pkg-manager/core/src/install/link.ts +++ b/pkg-manager/core/src/install/link.ts @@ -68,6 +68,7 @@ export interface LinkPackagesOptions { skipped: Set storeController: StoreController virtualStoreDir: string + virtualStoreDirMaxLength: number wantedLockfile: Lockfile wantedToBeSkippedPackageIds: Set hoistWorkspacePackages?: boolean @@ -117,6 +118,7 @@ export async function linkPackages (projects: ImporterToUpdate[], depGraph: Depe skipped: opts.skipped, storeController: opts.storeController, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, wantedLockfile: opts.wantedLockfile, }) @@ -224,6 +226,7 @@ export async function linkPackages (projects: ImporterToUpdate[], depGraph: Depe publicHoistedModulesDir: opts.rootModulesDir, publicHoistPattern: opts.publicHoistPattern ?? [], virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, hoistedWorkspacePackages: opts.hoistWorkspacePackages ? projects.reduce((hoistedWorkspacePackages, project) => { if (project.manifest.name && project.id !== '.') { diff --git a/pkg-manager/core/test/install/fromRepo.ts b/pkg-manager/core/test/install/fromRepo.ts index befe5f9d2b7..393890184f5 100644 --- a/pkg-manager/core/test/install/fromRepo.ts +++ b/pkg-manager/core/test/install/fromRepo.ts @@ -140,7 +140,7 @@ test('a subdependency is from a github repo with different name', async () => { project.isExecutable('@pnpm.e2e/has-aliased-git-dependency/node_modules/.bin/hi') project.isExecutable('@pnpm.e2e/has-aliased-git-dependency/node_modules/.bin/szia') - expect(fs.existsSync(path.resolve(`node_modules/.pnpm/${depPathToFilename('@pnpm.e2e/has-say-hi-peer@1.0.0(hi@https://codeload.github.com/zkochan/hi/tar.gz/4cdebec76b7b9d1f6e219e06c42d92a6b8ea60cd)')}/node_modules/@pnpm.e2e/has-say-hi-peer`))).toBeTruthy() + expect(fs.existsSync(path.resolve(`node_modules/.pnpm/${depPathToFilename('@pnpm.e2e/has-say-hi-peer@1.0.0(hi@https://codeload.github.com/zkochan/hi/tar.gz/4cdebec76b7b9d1f6e219e06c42d92a6b8ea60cd)', 120)}/node_modules/@pnpm.e2e/has-say-hi-peer`))).toBeTruthy() }) test('from a git repo', async () => { diff --git a/pkg-manager/core/test/install/peerDependencies.ts b/pkg-manager/core/test/install/peerDependencies.ts index d4d2163623c..68d844fcc57 100644 --- a/pkg-manager/core/test/install/peerDependencies.ts +++ b/pkg-manager/core/test/install/peerDependencies.ts @@ -550,7 +550,7 @@ test('peer dependencies are linked when running one named installation', async ( const pkgVariation1 = path.join( 'node_modules/.pnpm', - depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`), + depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`, 120), 'node_modules' ) await okFile(path.join(pkgVariation1, '@pnpm.e2e/abc')) @@ -561,7 +561,7 @@ test('peer dependencies are linked when running one named installation', async ( const pkgVariation2 = path.join( 'node_modules/.pnpm', - depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`), + depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`, 120), 'node_modules' ) await okFile(path.join(pkgVariation2, '@pnpm.e2e/abc')) @@ -589,7 +589,7 @@ test('peer dependencies are linked when running two separate named installations const pkgVariation1 = path.join( 'node_modules/.pnpm', - depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`), + depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`, 120), 'node_modules' ) await okFile(path.join(pkgVariation1, '@pnpm.e2e/abc')) @@ -600,7 +600,7 @@ test('peer dependencies are linked when running two separate named installations const pkgVariation2 = path.join( 'node_modules/.pnpm', - depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '2.0.0' }])}`), + depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '2.0.0' }])}`, 120), 'node_modules' ) await okFile(path.join(pkgVariation2, '@pnpm.e2e/abc')) @@ -661,7 +661,7 @@ test('peer bins are linked', async () => { await addDependenciesToPackage({}, ['@pnpm.e2e/for-testing-peers-having-bins'], testDefaults({ fastUnpack: false })) const suffix = createPeersDirSuffix([{ name: '@pnpm.e2e/peer-with-bin', version: '1.0.0' }]) - const pkgVariation = path.join('.pnpm', depPathToFilename(`@pnpm.e2e/pkg-with-peer-having-bin@1.0.0${suffix}`), 'node_modules') + const pkgVariation = path.join('.pnpm', depPathToFilename(`@pnpm.e2e/pkg-with-peer-having-bin@1.0.0${suffix}`, 120), 'node_modules') project.isExecutable(path.join(pkgVariation, '@pnpm.e2e/pkg-with-peer-having-bin/node_modules/.bin', 'peer-with-bin')) diff --git a/pkg-manager/core/test/install/virtualStoreDirMaxLength.ts b/pkg-manager/core/test/install/virtualStoreDirMaxLength.ts new file mode 100644 index 00000000000..7b2c387d83c --- /dev/null +++ b/pkg-manager/core/test/install/virtualStoreDirMaxLength.ts @@ -0,0 +1,17 @@ +import fs from 'fs' +import { addDependenciesToPackage } from '@pnpm/core' +import { prepareEmpty } from '@pnpm/prepare' +import { testDefaults } from '../utils' + +test('setting a custom virtual store directory max length', async () => { + prepareEmpty() + + await addDependenciesToPackage({}, ['@babel/helper-member-expression-to-functions@7.23.0'], testDefaults({ + virtualStoreDirMaxLength: 50, + })) + + const dirs = fs.readdirSync('node_modules/.pnpm') + for (const dir of dirs) { + expect(dir.length).toBeLessThanOrEqual(50) + } +}) diff --git a/pkg-manager/get-context/src/index.ts b/pkg-manager/get-context/src/index.ts index 6e1118a84ac..0af7d4fd03d 100644 --- a/pkg-manager/get-context/src/index.ts +++ b/pkg-manager/get-context/src/index.ts @@ -52,6 +52,7 @@ export interface PnpmContext { publicHoistPattern: string[] | undefined lockfileDir: string virtualStoreDir: string + virtualStoreDirMaxLength: number skipped: Set storeDir: string wantedLockfile: Lockfile @@ -92,6 +93,7 @@ export interface GetContextOptions { useGitBranchLockfile?: boolean mergeGitBranchLockfiles?: boolean virtualStoreDir?: string + virtualStoreDirMaxLength: number hoistPattern?: string[] | undefined forceHoistPattern?: boolean @@ -180,6 +182,7 @@ export async function getContext ( skipped: importersContext.skipped, storeDir: opts.storeDir, virtualStoreDir, + virtualStoreDirMaxLength: importersContext.virtualStoreDirMaxLength ?? opts.virtualStoreDirMaxLength, ...await readLockfiles({ autoInstallPeers: opts.autoInstallPeers, excludeLinksFromLockfile: opts.excludeLinksFromLockfile, diff --git a/pkg-manager/get-context/test/index.ts b/pkg-manager/get-context/test/index.ts index aebbf405b64..78a8b450987 100644 --- a/pkg-manager/get-context/test/index.ts +++ b/pkg-manager/get-context/test/index.ts @@ -20,6 +20,7 @@ const DEFAULT_OPTIONS: GetContextOptions = { optionalDependencies: true, }, storeDir: path.join(__dirname, 'store'), + virtualStoreDirMaxLength: 120, } test('getContext - extendNodePath false', async () => { diff --git a/pkg-manager/headless/src/index.ts b/pkg-manager/headless/src/index.ts index a5d79a5ddac..c5fc6afd050 100644 --- a/pkg-manager/headless/src/index.ts +++ b/pkg-manager/headless/src/index.ts @@ -129,6 +129,7 @@ export interface HeadlessOptions { lockfileDir: string modulesDir?: string virtualStoreDir?: string + virtualStoreDirMaxLength: number patchedDependencies?: Record scriptsPrependNodePath?: boolean | 'warn-only' scriptShell?: string @@ -248,6 +249,7 @@ export async function headlessInstall (opts: HeadlessOptions): Promise { if (project.manifest.name && project.id !== '.') { @@ -531,6 +535,7 @@ export async function headlessInstall (opts: HeadlessOptions): Promise 0, }) diff --git a/pkg-manager/hoist/src/index.ts b/pkg-manager/hoist/src/index.ts index 89a5e4955ca..7edeac34f66 100644 --- a/pkg-manager/hoist/src/index.ts +++ b/pkg-manager/hoist/src/index.ts @@ -24,6 +24,7 @@ export interface HoistOpts extends GetHoistedDependenciesOpts { extraNodePath?: string[] preferSymlinkedExecutables?: boolean virtualStoreDir: string + virtualStoreDirMaxLength: number } export async function hoist (opts: HoistOpts): Promise { @@ -36,6 +37,7 @@ export async function hoist (opts: HoistOpts): Promise { privateHoistedModulesDir: opts.privateHoistedModulesDir, publicHoistedModulesDir: opts.publicHoistedModulesDir, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, hoistedWorkspacePackages: opts.hoistedWorkspacePackages, }) @@ -244,6 +246,7 @@ async function symlinkHoistedDependencies ( privateHoistedModulesDir: string publicHoistedModulesDir: string virtualStoreDir: string + virtualStoreDirMaxLength: number hoistedWorkspacePackages?: Record } ): Promise { @@ -255,7 +258,7 @@ async function symlinkHoistedDependencies ( let depLocation!: string if (pkgSnapshot) { const pkgName = nameVerFromPkgSnapshot(hoistedDepId, pkgSnapshot).name - const modules = path.join(opts.virtualStoreDir, dp.depPathToFilename(hoistedDepId), 'node_modules') + const modules = path.join(opts.virtualStoreDir, dp.depPathToFilename(hoistedDepId, opts.virtualStoreDirMaxLength), 'node_modules') depLocation = path.join(modules, pkgName as string) } else { if (!opts.lockfile.importers[hoistedDepId]) { diff --git a/pkg-manager/modules-cleaner/src/prune.ts b/pkg-manager/modules-cleaner/src/prune.ts index d48cf8bc57b..cff5744f54f 100644 --- a/pkg-manager/modules-cleaner/src/prune.ts +++ b/pkg-manager/modules-cleaner/src/prune.ts @@ -49,6 +49,7 @@ export async function prune ( pruneVirtualStore?: boolean skipped: Set virtualStoreDir: string + virtualStoreDirMaxLength: number lockfileDir: string storeController: StoreController } @@ -169,13 +170,13 @@ export async function prune ( const _tryRemovePkg = tryRemovePkg.bind(null, opts.lockfileDir, opts.virtualStoreDir) await Promise.all( orphanDepPaths - .map((orphanDepPath) => depPathToFilename(orphanDepPath)) + .map((orphanDepPath) => depPathToFilename(orphanDepPath, opts.virtualStoreDirMaxLength)) .map(async (orphanDepPath) => _tryRemovePkg(orphanDepPath)) ) const neededPkgs = new Set(['node_modules']) for (const depPath of Object.keys(opts.wantedLockfile.packages ?? {})) { if (opts.skipped.has(depPath)) continue - neededPkgs.add(depPathToFilename(depPath)) + neededPkgs.add(depPathToFilename(depPath, opts.virtualStoreDirMaxLength)) } const availablePkgs = await readVirtualStoreDir(opts.virtualStoreDir, opts.lockfileDir) await Promise.all( diff --git a/pkg-manager/modules-yaml/src/index.ts b/pkg-manager/modules-yaml/src/index.ts index 22511a508b1..c577d019ecd 100644 --- a/pkg-manager/modules-yaml/src/index.ts +++ b/pkg-manager/modules-yaml/src/index.ts @@ -29,6 +29,7 @@ export interface Modules { skipped: string[] storeDir: string virtualStoreDir: string + virtualStoreDirMaxLength: number injectedDeps?: Record hoistedLocations?: Record } @@ -80,6 +81,9 @@ export async function readModulesManifest (modulesDir: string): Promise { skipped: [], storeDir: '/.pnpm-store', virtualStoreDir: path.join(modulesDir, '.pnpm'), + virtualStoreDirMaxLength: 120, } await writeModulesManifest(modulesDir, modulesYaml) expect(await readModulesManifest(modulesDir)).toEqual(modulesYaml) @@ -83,6 +84,7 @@ test('readModulesManifest() should not create a node_modules directory if it doe skipped: [], storeDir: '/.pnpm-store', virtualStoreDir: path.join(modulesDir, '.pnpm'), + virtualStoreDirMaxLength: 120, } await writeModulesManifest(modulesDir, modulesYaml) expect(fs.existsSync(modulesDir)).toBeFalsy() @@ -109,6 +111,7 @@ test('readModulesManifest() should create a node_modules directory if makeModule skipped: [], storeDir: '/.pnpm-store', virtualStoreDir: path.join(modulesDir, '.pnpm'), + virtualStoreDirMaxLength: 120, } await writeModulesManifest(modulesDir, modulesYaml, { makeModulesDir: true }) expect(await readModulesManifest(modulesDir)).toEqual(modulesYaml) diff --git a/pkg-manager/package-requester/src/packageRequester.ts b/pkg-manager/package-requester/src/packageRequester.ts index 975fb6b1ca1..82b8cf9cf95 100644 --- a/pkg-manager/package-requester/src/packageRequester.ts +++ b/pkg-manager/package-requester/src/packageRequester.ts @@ -90,6 +90,7 @@ export function createPackageRequester ( networkConcurrency?: number storeDir: string verifyStoreIntegrity: boolean + virtualStoreDirMaxLength: number } ): RequestPackageFunction & { fetchPackageToStore: FetchPackageToStoreFunction @@ -120,6 +121,7 @@ export function createPackageRequester ( concurrency: networkConcurrency, }), storeDir: opts.storeDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }) const requestPackage = resolveAndFetch.bind(null, { engineStrict: opts.engineStrict, @@ -137,6 +139,7 @@ export function createPackageRequester ( getFilesIndexFilePath: getFilesIndexFilePath.bind(null, { getFilePathInCafs, storeDir: opts.storeDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }), requestPackage, }) @@ -306,10 +309,11 @@ function getFilesIndexFilePath ( ctx: { getFilePathInCafs: (integrity: string, fileType: FileType) => string storeDir: string + virtualStoreDirMaxLength: number }, opts: Pick ) { - const targetRelative = depPathToFilename(opts.pkg.id) + const targetRelative = depPathToFilename(opts.pkg.id, ctx.virtualStoreDirMaxLength) const target = path.join(ctx.storeDir, targetRelative) const filesIndexFile = (opts.pkg.resolution as TarballResolution).integrity ? ctx.getFilePathInCafs((opts.pkg.resolution as TarballResolution).integrity!, 'index') @@ -337,6 +341,7 @@ function fetchToStore ( concurrency: number } storeDir: string + virtualStoreDirMaxLength: number }, opts: FetchPackageToStoreOptions ): { diff --git a/pkg-manager/package-requester/test/index.ts b/pkg-manager/package-requester/test/index.ts index a76f059659e..00ce3ae51d1 100644 --- a/pkg-manager/package-requester/test/index.ts +++ b/pkg-manager/package-requester/test/index.ts @@ -39,6 +39,7 @@ test('request package', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) expect(typeof requestPackage).toBe('function') @@ -80,6 +81,7 @@ test('request package but skip fetching', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) expect(typeof requestPackage).toBe('function') @@ -119,6 +121,7 @@ test('request package but skip fetching, when resolution is already available', networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) expect(typeof requestPackage).toBe('function') @@ -188,6 +191,7 @@ test('refetch local tarball if its integrity has changed', async () => { cafs, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const response = await requestPackage(wantedPackage, { @@ -219,6 +223,7 @@ test('refetch local tarball if its integrity has changed', async () => { cafs, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const response = await requestPackage(wantedPackage, { @@ -245,6 +250,7 @@ test('refetch local tarball if its integrity has changed', async () => { cafs, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const response = await requestPackage(wantedPackage, { @@ -291,6 +297,7 @@ test('refetch local tarball if its integrity has changed. The requester does not cafs, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const response = await requestPackage(wantedPackage, requestPackageOpts) as PackageResponse & { @@ -313,6 +320,7 @@ test('refetch local tarball if its integrity has changed. The requester does not cafs, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const response = await requestPackage(wantedPackage, requestPackageOpts) as PackageResponse & { @@ -332,6 +340,7 @@ test('refetch local tarball if its integrity has changed. The requester does not cafs, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const response = await requestPackage(wantedPackage, requestPackageOpts) as PackageResponse & { @@ -354,6 +363,7 @@ test('fetchPackageToStore()', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const pkgId = 'is-positive@1.0.0' @@ -419,6 +429,7 @@ test('fetchPackageToStore() concurrency check', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const pkgId = 'is-positive@1.0.0' @@ -504,6 +515,7 @@ test('fetchPackageToStore() does not cache errors', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const pkgId = 'is-positive@1.0.0' @@ -555,6 +567,7 @@ test('always return a package manifest in the response', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) expect(typeof requestPackage).toBe('function') const projectDir = tempy.directory() @@ -617,6 +630,7 @@ test('fetchPackageToStore() fetch raw manifest of cached package', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const pkgId = 'is-positive@1.0.0' @@ -671,6 +685,7 @@ test('refetch package to store if it has been modified', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const fetchResult = packageRequester.fetchPackageToStore({ @@ -709,6 +724,7 @@ test('refetch package to store if it has been modified', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const fetchResult = packageRequester.fetchPackageToStore({ @@ -732,7 +748,7 @@ test('refetch package to store if it has been modified', async () => { expect(reporter).toHaveBeenCalledWith(expect.objectContaining({ level: 'warn', - message: `Refetching ${path.join(storeDir, depPathToFilename(pkgId))} to store. It was either modified or had no integrity checksums`, + message: `Refetching ${path.join(storeDir, depPathToFilename(pkgId, 120))} to store. It was either modified or had no integrity checksums`, name: 'pnpm:package-requester', prefix: lockfileDir, })) @@ -748,6 +764,7 @@ test('do not fetch an optional package that is not installable', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) expect(typeof requestPackage).toBe('function') @@ -785,6 +802,7 @@ test('fetch a git package without a package.json', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) expect(typeof requestPackage).toBe('function') const projectDir = tempy.directory() @@ -818,6 +836,7 @@ test('throw exception if the package data in the store differs from the expected networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const projectDir = tempy.directory() @@ -840,6 +859,7 @@ test('throw exception if the package data in the store differs from the expected networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const { fetching } = requestPackage.fetchPackageToStore({ force: false, @@ -867,6 +887,7 @@ test('throw exception if the package data in the store differs from the expected networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const { fetching } = requestPackage.fetchPackageToStore({ force: false, @@ -894,6 +915,7 @@ test('throw exception if the package data in the store differs from the expected networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const { fetching } = requestPackage.fetchPackageToStore({ force: false, @@ -920,6 +942,7 @@ test('throw exception if the package data in the store differs from the expected networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const { fetching } = requestPackage.fetchPackageToStore({ force: false, @@ -950,6 +973,7 @@ test("don't throw an error if the package was updated, so the expectedPkg has a networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const projectDir = tempy.directory() @@ -969,6 +993,7 @@ test("don't throw an error if the package was updated, so the expectedPkg has a networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const projectDir = tempy.directory() const pkgResponse = await requestPackage({ alias: 'is-positive', pref: '3.1.0' }, { @@ -996,6 +1021,7 @@ test('the version in the bundled manifest should be normalized', async () => { networkConcurrency: 1, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const pkgResponse = await requestPackage({ alias: 'react-terminal', pref: '1.2.1' }, { @@ -1024,6 +1050,7 @@ test('should skip store integrity check and resolve manifest if fetchRawManifest networkConcurrency: 1, storeDir, verifyStoreIntegrity: false, + virtualStoreDirMaxLength: 120, }) const projectDir = tempy.directory() @@ -1047,6 +1074,7 @@ test('should skip store integrity check and resolve manifest if fetchRawManifest networkConcurrency: 1, storeDir, verifyStoreIntegrity: false, + virtualStoreDirMaxLength: 120, }) const fetchResult = requestPackage.fetchPackageToStore({ diff --git a/pkg-manager/plugin-commands-installation/test/add.ts b/pkg-manager/plugin-commands-installation/test/add.ts index 8323b0d94ec..30fa8d976c4 100644 --- a/pkg-manager/plugin-commands-installation/test/add.ts +++ b/pkg-manager/plugin-commands-installation/test/add.ts @@ -37,6 +37,7 @@ const DEFAULT_OPTIONS = { storeDir: path.join(tmp, 'store'), userConfig: {}, workspaceConcurrency: 1, + virtualStoreDirMaxLength: 120, } test('installing with "workspace:" should work even if link-workspace-packages is off', async () => { diff --git a/pkg-manager/plugin-commands-installation/test/fetch.ts b/pkg-manager/plugin-commands-installation/test/fetch.ts index 9d5379260f8..61aaeff6dfb 100644 --- a/pkg-manager/plugin-commands-installation/test/fetch.ts +++ b/pkg-manager/plugin-commands-installation/test/fetch.ts @@ -32,6 +32,7 @@ const DEFAULT_OPTIONS = { sort: true, userConfig: {}, workspaceConcurrency: 1, + virtualStoreDirMaxLength: 120, } test('fetch dependencies', async () => { diff --git a/pkg-manager/plugin-commands-installation/test/global.ts b/pkg-manager/plugin-commands-installation/test/global.ts index 3aec261561f..9394bf193e8 100644 --- a/pkg-manager/plugin-commands-installation/test/global.ts +++ b/pkg-manager/plugin-commands-installation/test/global.ts @@ -36,6 +36,7 @@ const DEFAULT_OPTIONS = { storeDir: path.join(tmp, 'store'), userConfig: {}, workspaceConcurrency: 1, + virtualStoreDirMaxLength: 120, } test('globally installed package is linked with active version of Node.js', async () => { diff --git a/pkg-manager/plugin-commands-installation/test/import.ts b/pkg-manager/plugin-commands-installation/test/import.ts index c1672ba9be2..f19579017dc 100644 --- a/pkg-manager/plugin-commands-installation/test/import.ts +++ b/pkg-manager/plugin-commands-installation/test/import.ts @@ -40,6 +40,7 @@ const DEFAULT_OPTS = { userConfig: {}, useRunningStoreServer: false, useStoreServer: false, + virtualStoreDirMaxLength: 120, } test('import from package-lock.json', async () => { diff --git a/pkg-manager/plugin-commands-installation/test/importRecursive.ts b/pkg-manager/plugin-commands-installation/test/importRecursive.ts index 960695fc7d9..e552bca94d3 100644 --- a/pkg-manager/plugin-commands-installation/test/importRecursive.ts +++ b/pkg-manager/plugin-commands-installation/test/importRecursive.ts @@ -38,6 +38,7 @@ const DEFAULT_OPTS = { userConfig: {}, useRunningStoreServer: false, useStoreServer: false, + virtualStoreDirMaxLength: 120, } test('import from shared yarn.lock of monorepo', async () => { diff --git a/pkg-manager/plugin-commands-installation/test/peerDependencies.ts b/pkg-manager/plugin-commands-installation/test/peerDependencies.ts index cbdee2c5f1c..0b3dad7c48e 100644 --- a/pkg-manager/plugin-commands-installation/test/peerDependencies.ts +++ b/pkg-manager/plugin-commands-installation/test/peerDependencies.ts @@ -35,6 +35,7 @@ const DEFAULT_OPTIONS = { storeDir: path.join(TMP, 'store'), userConfig: {}, workspaceConcurrency: 1, + virtualStoreDirMaxLength: 120, } test('root dependency that has a peer is correctly updated after its version changes', async () => { diff --git a/pkg-manager/plugin-commands-installation/test/prune.ts b/pkg-manager/plugin-commands-installation/test/prune.ts index 511f55de407..0b32075710b 100644 --- a/pkg-manager/plugin-commands-installation/test/prune.ts +++ b/pkg-manager/plugin-commands-installation/test/prune.ts @@ -36,6 +36,7 @@ const DEFAULT_OPTIONS = { sort: true, userConfig: {}, workspaceConcurrency: 1, + virtualStoreDirMaxLength: 120, } test('prune removes external link that is not in package.json', async () => { diff --git a/pkg-manager/plugin-commands-installation/test/update/interactive.ts b/pkg-manager/plugin-commands-installation/test/update/interactive.ts index bc50984616c..64be2e621a1 100644 --- a/pkg-manager/plugin-commands-installation/test/update/interactive.ts +++ b/pkg-manager/plugin-commands-installation/test/update/interactive.ts @@ -41,6 +41,7 @@ const DEFAULT_OPTIONS = { sort: true, userConfig: {}, workspaceConcurrency: 1, + virtualStoreDirMaxLength: 120, } test('interactively update', async () => { diff --git a/pkg-manager/plugin-commands-installation/test/update/issue-7415.ts b/pkg-manager/plugin-commands-installation/test/update/issue-7415.ts index 005bfe2bfa6..65606695970 100644 --- a/pkg-manager/plugin-commands-installation/test/update/issue-7415.ts +++ b/pkg-manager/plugin-commands-installation/test/update/issue-7415.ts @@ -38,6 +38,7 @@ const DEFAULT_OPTIONS = { sort: true, userConfig: {}, workspaceConcurrency: 1, + virtualStoreDirMaxLength: 120, } test('interactive recursive should not error on git specifier override', async () => { diff --git a/pkg-manager/plugin-commands-installation/test/utils/index.ts b/pkg-manager/plugin-commands-installation/test/utils/index.ts index 6c65333b736..021d4d8c268 100644 --- a/pkg-manager/plugin-commands-installation/test/utils/index.ts +++ b/pkg-manager/plugin-commands-installation/test/utils/index.ts @@ -49,4 +49,5 @@ export const DEFAULT_OPTS = { useRunningStoreServer: false, useStoreServer: false, workspaceConcurrency: 4, + virtualStoreDirMaxLength: 120, } diff --git a/pkg-manager/read-projects-context/src/index.ts b/pkg-manager/read-projects-context/src/index.ts index 6522888251f..60d36a71aca 100644 --- a/pkg-manager/read-projects-context/src/index.ts +++ b/pkg-manager/read-projects-context/src/index.ts @@ -31,6 +31,7 @@ export async function readProjectsContext ( registries: Registries | null | undefined rootModulesDir: string skipped: Set + virtualStoreDirMaxLength?: number }> { const relativeModulesDir = opts.modulesDir ?? 'node_modules' const rootModulesDir = await realpathMissing(path.join(opts.lockfileDir, relativeModulesDir)) @@ -58,5 +59,6 @@ export async function readProjectsContext ( registries: ((modules?.registries) != null) ? normalizeRegistries(modules.registries) : undefined, rootModulesDir, skipped: new Set(modules?.skipped ?? []), + virtualStoreDirMaxLength: modules?.virtualStoreDirMaxLength, } } diff --git a/pkg-manager/resolve-dependencies/src/index.ts b/pkg-manager/resolve-dependencies/src/index.ts index cf66732ff26..7bb96a559f5 100644 --- a/pkg-manager/resolve-dependencies/src/index.ts +++ b/pkg-manager/resolve-dependencies/src/index.ts @@ -197,6 +197,7 @@ export async function resolveDependencies ( lockfileDir: opts.lockfileDir, projects: projectsToLink, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, resolvePeersFromWorkspaceRoot: Boolean(opts.resolvePeersFromWorkspaceRoot), resolvedImporters, }) diff --git a/pkg-manager/resolve-dependencies/src/resolveDependencies.ts b/pkg-manager/resolve-dependencies/src/resolveDependencies.ts index ed2e409c69f..beefe0f8c04 100644 --- a/pkg-manager/resolve-dependencies/src/resolveDependencies.ts +++ b/pkg-manager/resolve-dependencies/src/resolveDependencies.ts @@ -164,6 +164,7 @@ export interface ResolutionContext { registries: Registries resolutionMode?: 'highest' | 'time-based' | 'lowest-direct' virtualStoreDir: string + virtualStoreDirMaxLength: number workspacePackages?: WorkspacePackages missingPeersOfChildrenByPkgId: Record hoistPeers?: boolean @@ -1104,7 +1105,7 @@ async function resolveDependency ( await exists( path.join( ctx.virtualStoreDir, - dp.depPathToFilename(currentPkg.depPath), + dp.depPathToFilename(currentPkg.depPath, ctx.virtualStoreDirMaxLength), 'node_modules', currentPkg.name, 'package.json' diff --git a/pkg-manager/resolve-dependencies/src/resolveDependencyTree.ts b/pkg-manager/resolve-dependencies/src/resolveDependencyTree.ts index 644c5d0334a..bf58642f9ae 100644 --- a/pkg-manager/resolve-dependencies/src/resolveDependencyTree.ts +++ b/pkg-manager/resolve-dependencies/src/resolveDependencyTree.ts @@ -99,6 +99,7 @@ export interface ResolveDependenciesOptions { storeController: StoreController tag: string virtualStoreDir: string + virtualStoreDirMaxLength: number wantedLockfile: Lockfile workspacePackages: WorkspacePackages supportedArchitectures?: SupportedArchitectures @@ -152,6 +153,7 @@ export async function resolveDependencyTree ( skipped: wantedToBeSkippedPackageIds, storeController: opts.storeController, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, wantedLockfile: opts.wantedLockfile, appliedPatches: new Set(), updatedSet: new Set(), diff --git a/pkg-manager/resolve-dependencies/src/resolvePeers.ts b/pkg-manager/resolve-dependencies/src/resolvePeers.ts index 7e1b6cedc10..d65822d4023 100644 --- a/pkg-manager/resolve-dependencies/src/resolvePeers.ts +++ b/pkg-manager/resolve-dependencies/src/resolvePeers.ts @@ -69,6 +69,7 @@ export async function resolvePeers ( projects: ProjectToResolve[] dependenciesTree: DependenciesTree virtualStoreDir: string + virtualStoreDirMaxLength: number lockfileDir: string resolvePeersFromWorkspaceRoot?: boolean dedupePeerDependents?: boolean @@ -114,6 +115,7 @@ export async function resolvePeers ( purePkgs: new Set(), rootDir, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }) if (finishing) { finishingList.push(finishing) @@ -312,6 +314,7 @@ async function resolvePeersOfNode ( dependenciesTree: DependenciesTree depGraph: GenericDependenciesGraph virtualStoreDir: string + virtualStoreDirMaxLength: number peerDependencyIssues: Pick peersCache: PeersCache purePkgs: Set // pure packages are those that don't rely on externally resolved peers @@ -510,7 +513,7 @@ async function resolvePeersOfNode ( } const peerDependencies = { ...resolvedPackage.peerDependencies } if (!ctx.depGraph[depPath] || ctx.depGraph[depPath].depth > node.depth) { - const modules = path.join(ctx.virtualStoreDir, depPathToFilename(depPath), 'node_modules') + const modules = path.join(ctx.virtualStoreDir, depPathToFilename(depPath, ctx.virtualStoreDirMaxLength), 'node_modules') const dir = path.join(modules, resolvedPackage.name) const transitivePeerDependencies = new Set() @@ -584,6 +587,7 @@ async function resolvePeersOfChildren ( peerDependencyIssues: Pick peersCache: PeersCache virtualStoreDir: string + virtualStoreDirMaxLength: number purePkgs: Set depGraph: GenericDependenciesGraph dependenciesTree: DependenciesTree diff --git a/pkg-manager/resolve-dependencies/test/dedupeDepPaths.test.ts b/pkg-manager/resolve-dependencies/test/dedupeDepPaths.test.ts index 1dcb8664541..ff9114ae670 100644 --- a/pkg-manager/resolve-dependencies/test/dedupeDepPaths.test.ts +++ b/pkg-manager/resolve-dependencies/test/dedupeDepPaths.test.ts @@ -96,6 +96,7 @@ test('packages are not deduplicated when versions do not match', async () => { } as DependenciesTreeNode])), dedupePeerDependents: true, virtualStoreDir: '', + virtualStoreDirMaxLength: 120, lockfileDir: '', }) diff --git a/pkg-manager/resolve-dependencies/test/resolvePeers.ts b/pkg-manager/resolve-dependencies/test/resolvePeers.ts index ad2c93ee720..1ea94b16cb9 100644 --- a/pkg-manager/resolve-dependencies/test/resolvePeers.ts +++ b/pkg-manager/resolve-dependencies/test/resolvePeers.ts @@ -102,6 +102,7 @@ test('resolve peer dependencies of cyclic dependencies', async () => { ]), virtualStoreDir: '', lockfileDir: '', + virtualStoreDirMaxLength: 120, }) expect(Object.keys(dependenciesGraph)).toStrictEqual([ 'foo/1.0.0', @@ -202,6 +203,7 @@ test('when a package is referenced twice in the dependencies graph and one of th }], ]), virtualStoreDir: '', + virtualStoreDirMaxLength: 120, lockfileDir: '', }) expect(Object.keys(dependenciesGraph).sort()).toStrictEqual([ @@ -381,6 +383,7 @@ describe('peer dependency issues', () => { }], ]), virtualStoreDir: '', + virtualStoreDirMaxLength: 120, lockfileDir: '', })).peerDependencyIssuesByProjects }) @@ -464,6 +467,7 @@ describe('unmet peer dependency issues', () => { }], ]), virtualStoreDir: '', + virtualStoreDirMaxLength: 120, lockfileDir: '', })).peerDependencyIssuesByProjects }) @@ -534,6 +538,7 @@ describe('unmet peer dependency issue resolved from subdependency', () => { }], ]), virtualStoreDir: '', + virtualStoreDirMaxLength: 120, lockfileDir: '', })).peerDependencyIssuesByProjects }) @@ -633,6 +638,7 @@ test('resolve peer dependencies with npm aliases', async () => { }], ]), virtualStoreDir: '', + virtualStoreDirMaxLength: 120, lockfileDir: '', }) expect(Object.keys(dependenciesGraph).sort()).toStrictEqual([ diff --git a/releasing/plugin-commands-deploy/test/utils/index.ts b/releasing/plugin-commands-deploy/test/utils/index.ts index 6c65333b736..021d4d8c268 100644 --- a/releasing/plugin-commands-deploy/test/utils/index.ts +++ b/releasing/plugin-commands-deploy/test/utils/index.ts @@ -49,4 +49,5 @@ export const DEFAULT_OPTS = { useRunningStoreServer: false, useStoreServer: false, workspaceConcurrency: 4, + virtualStoreDirMaxLength: 120, } diff --git a/releasing/plugin-commands-publishing/test/utils/index.ts b/releasing/plugin-commands-publishing/test/utils/index.ts index 5677cb64eb5..1ec75e1d851 100644 --- a/releasing/plugin-commands-publishing/test/utils/index.ts +++ b/releasing/plugin-commands-publishing/test/utils/index.ts @@ -45,4 +45,5 @@ export const DEFAULT_OPTS = { useRunningStoreServer: false, useStoreServer: false, workspaceConcurrency: 4, + virtualStoreDirMaxLength: 120, } diff --git a/reviewing/dependencies-hierarchy/src/buildDependenciesHierarchy.ts b/reviewing/dependencies-hierarchy/src/buildDependenciesHierarchy.ts index 816180c5138..36f511b7fd6 100644 --- a/reviewing/dependencies-hierarchy/src/buildDependenciesHierarchy.ts +++ b/reviewing/dependencies-hierarchy/src/buildDependenciesHierarchy.ts @@ -40,6 +40,7 @@ export async function buildDependenciesHierarchy ( search?: SearchFunction lockfileDir: string modulesDir?: string + virtualStoreDirMaxLength: number } ): Promise<{ [projectDir: string]: DependenciesHierarchy }> { if (!maybeOpts?.lockfileDir) { @@ -81,6 +82,7 @@ export async function buildDependenciesHierarchy ( skipped: new Set(modules?.skipped ?? []), modulesDir: maybeOpts.modulesDir, virtualStoreDir: modules?.virtualStoreDir, + virtualStoreDirMaxLength: modules?.virtualStoreDirMaxLength ?? maybeOpts.virtualStoreDirMaxLength, } ; ( await Promise.all(projectPaths.map(async (projectPath) => { @@ -109,6 +111,7 @@ async function dependenciesHierarchyForPackage ( lockfileDir: string modulesDir?: string virtualStoreDir?: string + virtualStoreDirMaxLength: number } ): Promise { const importerId = getLockfileImporterId(opts.lockfileDir, projectPath) @@ -137,6 +140,7 @@ async function dependenciesHierarchyForPackage ( skipped: opts.skipped, wantedPackages: wantedLockfile?.packages ?? {}, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }) const parentId: TreeNodeId = { type: 'importer', importerId } const result: DependenciesHierarchy = {} @@ -155,6 +159,7 @@ async function dependenciesHierarchyForPackage ( skipped: opts.skipped, wantedPackages: wantedLockfile?.packages ?? {}, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }) let newEntry: PackageNode | null = null const matchedSearched = opts.search?.(packageInfo) diff --git a/reviewing/dependencies-hierarchy/src/getPkgInfo.ts b/reviewing/dependencies-hierarchy/src/getPkgInfo.ts index 3e140ed48b4..8212acdcc39 100644 --- a/reviewing/dependencies-hierarchy/src/getPkgInfo.ts +++ b/reviewing/dependencies-hierarchy/src/getPkgInfo.ts @@ -22,6 +22,7 @@ export interface GetPkgInfoOpts { readonly skipped: Set readonly wantedPackages: PackageSnapshots readonly virtualStoreDir?: string + readonly virtualStoreDirMaxLength: number readonly depTypes: DepTypes /** @@ -79,7 +80,7 @@ export function getPkgInfo (opts: GetPkgInfoOpts): PackageInfo { version = opts.ref } const fullPackagePath = depPath - ? path.join(opts.virtualStoreDir ?? '.pnpm', depPathToFilename(depPath), 'node_modules', name) + ? path.join(opts.virtualStoreDir ?? '.pnpm', depPathToFilename(depPath, opts.virtualStoreDirMaxLength), 'node_modules', name) : path.join(opts.linkedPathBaseDir, opts.ref.slice(5)) if (version.startsWith('link:') && opts.rewriteLinkVersionDir) { diff --git a/reviewing/dependencies-hierarchy/src/getTree.ts b/reviewing/dependencies-hierarchy/src/getTree.ts index 5adbbd52ad9..09fa4885222 100644 --- a/reviewing/dependencies-hierarchy/src/getTree.ts +++ b/reviewing/dependencies-hierarchy/src/getTree.ts @@ -23,6 +23,7 @@ interface GetTreeOpts { currentPackages: PackageSnapshots wantedPackages: PackageSnapshots virtualStoreDir?: string + virtualStoreDirMaxLength: number } interface DependencyInfo { @@ -136,6 +137,7 @@ function getTreeHelper ( skipped: opts.skipped, wantedPackages: opts.wantedPackages, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }) let circular: boolean const matchedSearched = opts.search?.(packageInfo) diff --git a/reviewing/dependencies-hierarchy/test/getTree.test.ts b/reviewing/dependencies-hierarchy/test/getTree.test.ts index 7f49953aec9..7dc51702cc3 100644 --- a/reviewing/dependencies-hierarchy/test/getTree.test.ts +++ b/reviewing/dependencies-hierarchy/test/getTree.test.ts @@ -99,7 +99,7 @@ describe('getTree', () => { } test('full test case to print when max depth is large', () => { - const result = normalizePackageNodeForTesting(getTree({ ...getTreeArgs, maxDepth: 9999 }, rootNodeId)) + const result = normalizePackageNodeForTesting(getTree({ ...getTreeArgs, maxDepth: 9999, virtualStoreDirMaxLength: 120 }, rootNodeId)) expect(result).toEqual([ expect.objectContaining({ @@ -119,12 +119,12 @@ describe('getTree', () => { }) test('no result when current depth exceeds max depth', () => { - const result = getTree({ ...getTreeArgs, maxDepth: 0 }, rootNodeId) + const result = getTree({ ...getTreeArgs, maxDepth: 0, virtualStoreDirMaxLength: 120 }, rootNodeId) expect(result).toEqual([]) }) test('max depth of 1 to print flat dependencies', () => { - const result = getTree({ ...getTreeArgs, maxDepth: 1 }, rootNodeId) + const result = getTree({ ...getTreeArgs, maxDepth: 1, virtualStoreDirMaxLength: 120 }, rootNodeId) expect(normalizePackageNodeForTesting(result)).toEqual([ expect.objectContaining({ alias: 'b1', dependencies: undefined }), @@ -134,7 +134,7 @@ describe('getTree', () => { }) test('max depth of 2 to print a1 -> b1 -> c1, but not d1', () => { - const result = getTree({ ...getTreeArgs, maxDepth: 2 }, rootNodeId) + const result = getTree({ ...getTreeArgs, maxDepth: 2, virtualStoreDirMaxLength: 120 }, rootNodeId) expect(normalizePackageNodeForTesting(result)).toEqual([ expect.objectContaining({ @@ -197,6 +197,7 @@ describe('getTree', () => { maxDepth: 3, currentPackages, wantedPackages: currentPackages, + virtualStoreDirMaxLength: 120, }, rootNodeId) expect(normalizePackageNodeForTesting(result)).toEqual([ @@ -255,6 +256,7 @@ describe('getTree', () => { maxDepth: 3, currentPackages, wantedPackages: currentPackages, + virtualStoreDirMaxLength: 120, }, rootNodeId) expect(normalizePackageNodeForTesting(result)).toEqual([ @@ -306,6 +308,7 @@ describe('getTree', () => { registries: { default: 'mock-registry-for-testing.example', }, + virtualStoreDirMaxLength: 120, } // The fully visited cache can be used in this situation. diff --git a/reviewing/dependencies-hierarchy/test/index.ts b/reviewing/dependencies-hierarchy/test/index.ts index 59ee45f62c0..a639de3e724 100644 --- a/reviewing/dependencies-hierarchy/test/index.ts +++ b/reviewing/dependencies-hierarchy/test/index.ts @@ -19,7 +19,7 @@ const workspaceWithNestedWorkspaceDeps = f.find('workspace-with-nested-workspace const customModulesDirFixture = f.find('custom-modules-dir') test('one package depth 0', async () => { - const tree = await buildDependenciesHierarchy([generalFixture], { depth: 0, lockfileDir: generalFixture }) + const tree = await buildDependenciesHierarchy([generalFixture], { depth: 0, lockfileDir: generalFixture, virtualStoreDirMaxLength: 120 }) const modulesDir = path.join(generalFixture, 'node_modules') expect(tree).toStrictEqual({ @@ -80,7 +80,7 @@ test('one package depth 0', async () => { }) test('one package depth 1', async () => { - const tree = await buildDependenciesHierarchy([generalFixture], { depth: 1, lockfileDir: generalFixture }) + const tree = await buildDependenciesHierarchy([generalFixture], { depth: 1, lockfileDir: generalFixture, virtualStoreDirMaxLength: 120 }) const modulesDir = path.join(generalFixture, 'node_modules') expect(tree).toStrictEqual({ @@ -179,6 +179,7 @@ test('only prod depth 0', async () => { optionalDependencies: false, }, lockfileDir: generalFixture, + virtualStoreDirMaxLength: 120, } ) const modulesDir = path.join(generalFixture, 'node_modules') @@ -224,6 +225,7 @@ test('only dev depth 0', async () => { optionalDependencies: false, }, lockfileDir: generalFixture, + virtualStoreDirMaxLength: 120, } ) const modulesDir = path.join(generalFixture, 'node_modules') @@ -252,6 +254,7 @@ test('hierarchy for no packages', async () => { depth: 100, lockfileDir: generalFixture, search: () => false, + virtualStoreDirMaxLength: 120, }) expect(tree).toStrictEqual({ @@ -270,6 +273,7 @@ test('filter 1 package with depth 0', async () => { depth: 0, lockfileDir: generalFixture, search: ({ name }) => name === 'rimraf', + virtualStoreDirMaxLength: 120, } ) const modulesDir = path.join(generalFixture, 'node_modules') @@ -297,7 +301,11 @@ test('filter 1 package with depth 0', async () => { }) test('circular dependency', async () => { - const tree = await buildDependenciesHierarchy([circularFixture], { depth: 1000, lockfileDir: circularFixture }) + const tree = await buildDependenciesHierarchy([circularFixture], { + depth: 1000, + lockfileDir: circularFixture, + virtualStoreDirMaxLength: 120, + }) const modulesDir = path.join(circularFixture, 'node_modules') expect(tree).toStrictEqual({ @@ -329,7 +337,11 @@ function resolvePaths (modulesDir: string, node: PackageNode): PackageNode { } test('local package depth 0', async () => { - const tree = await buildDependenciesHierarchy([withFileDepFixture], { depth: 1, lockfileDir: withFileDepFixture }) + const tree = await buildDependenciesHierarchy([withFileDepFixture], { + depth: 1, + lockfileDir: withFileDepFixture, + virtualStoreDirMaxLength: 120, + }) const modulesDir = path.join(withFileDepFixture, 'node_modules') expect(tree).toStrictEqual({ @@ -363,7 +375,11 @@ test('local package depth 0', async () => { }) test('on a package that has only links', async () => { - const tree = await buildDependenciesHierarchy([withLinksOnlyFixture], { depth: 1000, lockfileDir: withLinksOnlyFixture }) + const tree = await buildDependenciesHierarchy([withLinksOnlyFixture], { + depth: 1000, + lockfileDir: withLinksOnlyFixture, + virtualStoreDirMaxLength: 120, + }) expect(tree).toStrictEqual({ [withLinksOnlyFixture]: { @@ -388,7 +404,11 @@ test('on a package that has only links', async () => { test('on a package with nested workspace links', async () => { const tree = await buildDependenciesHierarchy( [workspaceWithNestedWorkspaceDeps], - { depth: 1000, lockfileDir: workspaceWithNestedWorkspaceDeps } + { + depth: 1000, + lockfileDir: workspaceWithNestedWorkspaceDeps, + virtualStoreDirMaxLength: 120, + } ) expect(tree).toEqual({ @@ -426,7 +446,11 @@ test('on a package with nested workspace links', async () => { test('unsaved dependencies are listed', async () => { const modulesDir = path.join(withUnsavedDepsFixture, 'node_modules') - expect(await buildDependenciesHierarchy([withUnsavedDepsFixture], { depth: 0, lockfileDir: withUnsavedDepsFixture })) + expect(await buildDependenciesHierarchy([withUnsavedDepsFixture], { + depth: 0, + lockfileDir: withUnsavedDepsFixture, + virtualStoreDirMaxLength: 120, + })) .toStrictEqual({ [withUnsavedDepsFixture]: { dependencies: [ @@ -468,6 +492,7 @@ test('unsaved dependencies are listed and filtered', async () => { depth: 0, lockfileDir: withUnsavedDepsFixture, search: ({ name }) => name === 'symlink-dir', + virtualStoreDirMaxLength: 120, } ) ).toStrictEqual({ @@ -494,13 +519,21 @@ test('unsaved dependencies are listed and filtered', async () => { // Covers https://github.com/pnpm/pnpm/issues/1549 test(`do not fail on importers that are not in current ${WANTED_LOCKFILE}`, async () => { - expect(await buildDependenciesHierarchy([fixtureMonorepo], { depth: 0, lockfileDir: fixtureMonorepo })).toStrictEqual({ [fixtureMonorepo]: {} }) + expect(await buildDependenciesHierarchy([fixtureMonorepo], { + depth: 0, + lockfileDir: fixtureMonorepo, + virtualStoreDirMaxLength: 120, + })).toStrictEqual({ [fixtureMonorepo]: {} }) }) test('dependency with an alias', async () => { const modulesDir = path.join(withAliasedDepFixture, 'node_modules') expect( - await buildDependenciesHierarchy([withAliasedDepFixture], { depth: 0, lockfileDir: withAliasedDepFixture }) + await buildDependenciesHierarchy([withAliasedDepFixture], { + depth: 0, + lockfileDir: withAliasedDepFixture, + virtualStoreDirMaxLength: 120, + }) ).toStrictEqual({ [withAliasedDepFixture]: { dependencies: [ @@ -523,7 +556,11 @@ test('dependency with an alias', async () => { }) test('peer dependencies', async () => { - const hierarchy = await buildDependenciesHierarchy([withPeerFixture], { depth: 1, lockfileDir: withPeerFixture }) + const hierarchy = await buildDependenciesHierarchy([withPeerFixture], { + depth: 1, + lockfileDir: withPeerFixture, + virtualStoreDirMaxLength: 120, + }) expect(hierarchy[withPeerFixture].dependencies![1].dependencies![0].name).toEqual('ajv') expect(hierarchy[withPeerFixture].dependencies![1].dependencies![0].isPeer).toEqual(true) }) @@ -533,7 +570,11 @@ test('dependency without a package.json', async () => { const org = 'denolib' const pkg = 'camelcase' const commit = 'aeb6b15f9c9957c8fa56f9731e914c4d8a6d2f2b' - const tree = await buildDependenciesHierarchy([withNonPackageDepFixture], { depth: 0, lockfileDir: withNonPackageDepFixture }) + const tree = await buildDependenciesHierarchy([withNonPackageDepFixture], { + depth: 0, + lockfileDir: withNonPackageDepFixture, + virtualStoreDirMaxLength: 120, + }) const resolved = `https://codeload.github.com/${org}/${pkg}/tar.gz/${commit}` expect(tree).toStrictEqual({ [withNonPackageDepFixture]: { @@ -545,7 +586,7 @@ test('dependency without a package.json', async () => { isPeer: false, isSkipped: false, name: 'camelcase', - path: path.join(withNonPackageDepFixture, 'node_modules/.pnpm', `camelcase@${depPathToFilename(resolved)}`, 'node_modules/camelcase'), + path: path.join(withNonPackageDepFixture, 'node_modules/.pnpm', `camelcase@${depPathToFilename(resolved, 120)}`, 'node_modules/camelcase'), resolved, version: '0.0.0', }, @@ -568,7 +609,12 @@ test('dependency without a package.json', async () => { test('on custom modules-dir workspaces', async () => { const tree = await buildDependenciesHierarchy( [customModulesDirFixture, path.join(customModulesDirFixture, './packages/foo'), path.join(customModulesDirFixture, './packages/bar')], - { depth: 1000, lockfileDir: customModulesDirFixture, modulesDir: 'fake_modules' } + { + depth: 1000, + lockfileDir: customModulesDirFixture, + modulesDir: 'fake_modules', + virtualStoreDirMaxLength: 120, + } ) expect(tree).toEqual({ [customModulesDirFixture]: { diff --git a/reviewing/license-scanner/src/getPkgInfo.ts b/reviewing/license-scanner/src/getPkgInfo.ts index 67dda36c93c..d473e3f803a 100644 --- a/reviewing/license-scanner/src/getPkgInfo.ts +++ b/reviewing/license-scanner/src/getPkgInfo.ts @@ -220,6 +220,13 @@ export type ReadPackageIndexFileResult = | { local: false, files: Record } | { local: true, files: Record } +export interface ReadPackageIndexFileOptions { + cafsDir: string + storeDir: string + lockfileDir: string + virtualStoreDirMaxLength: number +} + /** * Returns the index of files included in * the package identified by the integrity id @@ -230,7 +237,7 @@ export type ReadPackageIndexFileResult = export async function readPackageIndexFile ( packageResolution: Resolution, id: string, - opts: { cafsDir: string, storeDir: string, lockfileDir: string } + opts: ReadPackageIndexFileOptions ): Promise { // If the package resolution is of type directory we need to do things // differently and generate our own package index file @@ -257,7 +264,7 @@ export async function readPackageIndexFile ( 'index' ) } else if (!packageResolution.type && packageResolution.tarball) { - const packageDirInStore = depPathToFilename(parse(id).nonSemverVersion ?? id) + const packageDirInStore = depPathToFilename(parse(id).nonSemverVersion ?? id, opts.virtualStoreDirMaxLength) pkgIndexFilePath = path.join( opts.storeDir, packageDirInStore, @@ -300,6 +307,7 @@ export interface PackageInfo { export interface GetPackageInfoOptions { storeDir: string virtualStoreDir: string + virtualStoreDirMaxLength: number dir: string modulesDir: string } @@ -334,6 +342,7 @@ export async function getPkgInfo ( cafsDir, storeDir: opts.storeDir, lockfileDir: opts.dir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, } ) @@ -377,7 +386,7 @@ export async function getPkgInfo ( // TODO: fix issue that path is only correct when using node-linked=isolated const packageModulePath = path.join( virtualStoreDir, - depPathToFilename(pkg.depPath), + depPathToFilename(pkg.depPath, opts.virtualStoreDirMaxLength), modulesDir, manifest.name ) diff --git a/reviewing/license-scanner/src/licenses.ts b/reviewing/license-scanner/src/licenses.ts index 28acd60266c..98854e07d22 100644 --- a/reviewing/license-scanner/src/licenses.ts +++ b/reviewing/license-scanner/src/licenses.ts @@ -73,6 +73,7 @@ export async function findDependencyLicenses (opts: { manifest: ProjectManifest storeDir: string virtualStoreDir: string + virtualStoreDirMaxLength: number modulesDir?: string registries: Registries wantedLockfile: Lockfile | null @@ -92,6 +93,7 @@ export async function findDependencyLicenses (opts: { modulesDir: opts.modulesDir, storeDir: opts.storeDir, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, include: opts.include, registries: opts.registries, includedImporterIds: opts.includedImporterIds, diff --git a/reviewing/license-scanner/src/lockfileToLicenseNodeTree.ts b/reviewing/license-scanner/src/lockfileToLicenseNodeTree.ts index b6abe65f86b..f2423d869b3 100644 --- a/reviewing/license-scanner/src/lockfileToLicenseNodeTree.ts +++ b/reviewing/license-scanner/src/lockfileToLicenseNodeTree.ts @@ -34,6 +34,7 @@ LicenseNode, export interface LicenseExtractOptions { storeDir: string virtualStoreDir: string + virtualStoreDirMaxLength: number modulesDir?: string dir: string registries: Registries @@ -80,6 +81,7 @@ export async function lockfileToLicenseNode ( { storeDir: options.storeDir, virtualStoreDir: options.virtualStoreDir, + virtualStoreDirMaxLength: options.virtualStoreDirMaxLength, dir: options.dir, modulesDir: options.modulesDir ?? 'node_modules', } @@ -140,6 +142,7 @@ export async function lockfileToLicenseNodeTree ( const importerDeps = await lockfileToLicenseNode(importerWalker.step, { storeDir: opts.storeDir, virtualStoreDir: opts.virtualStoreDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, modulesDir: opts.modulesDir, dir: opts.dir, registries: opts.registries, diff --git a/reviewing/license-scanner/test/getPkgInfo.spec.ts b/reviewing/license-scanner/test/getPkgInfo.spec.ts index c0cfd01c0b3..1ed067270e4 100644 --- a/reviewing/license-scanner/test/getPkgInfo.spec.ts +++ b/reviewing/license-scanner/test/getPkgInfo.spec.ts @@ -25,6 +25,7 @@ describe('licences', () => { virtualStoreDir: 'virtual-store-dir', modulesDir: 'modules-dir', dir: 'workspace-dir', + virtualStoreDirMaxLength: 120, } ) ).rejects.toThrow('Failed to find package index file for /bogus-package@1.0.0, please consider running \'pnpm install\'') diff --git a/reviewing/license-scanner/test/licenses.spec.ts b/reviewing/license-scanner/test/licenses.spec.ts index ee3e09b961f..4f051694dbc 100644 --- a/reviewing/license-scanner/test/licenses.spec.ts +++ b/reviewing/license-scanner/test/licenses.spec.ts @@ -71,6 +71,7 @@ describe('licences', () => { registries: {} as Registries, wantedLockfile: lockfile, storeDir: '/opt/.pnpm', + virtualStoreDirMaxLength: 120, }) expect(licensePackages).toEqual([ @@ -157,6 +158,7 @@ describe('licences', () => { wantedLockfile: lockfile, storeDir: '/opt/.pnpm', includedImporterIds: ['packages/a'], + virtualStoreDirMaxLength: 120, }) expect(licensePackages).toEqual([ @@ -232,6 +234,7 @@ describe('licences', () => { registries: {} as Registries, wantedLockfile: lockfile, storeDir: '/opt/.pnpm', + virtualStoreDirMaxLength: 120, }) expect(licensePackages).toEqual([ diff --git a/reviewing/list/src/index.ts b/reviewing/list/src/index.ts index b47743e8db1..6c7a7f4a241 100644 --- a/reviewing/list/src/index.ts +++ b/reviewing/list/src/index.ts @@ -64,6 +64,7 @@ export async function searchForPackages ( onlyProjects?: boolean registries?: Registries modulesDir?: string + virtualStoreDirMaxLength: number } ): Promise { const search = createPackagesSearcher(packages) @@ -77,6 +78,7 @@ export async function searchForPackages ( registries: opts.registries, search, modulesDir: opts.modulesDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, })) .map(async ([projectPath, buildDependenciesHierarchy]) => { const entryPkg = await safeReadProjectManifestOnly(projectPath) ?? {} @@ -104,6 +106,7 @@ export async function listForPackages ( reportAs?: 'parseable' | 'tree' | 'json' registries?: Registries modulesDir?: string + virtualStoreDirMaxLength: number } ): Promise { const opts = { ...DEFAULTS, ...maybeOpts } @@ -135,6 +138,7 @@ export async function list ( registries?: Registries showExtraneous?: boolean modulesDir?: string + virtualStoreDirMaxLength: number } ): Promise { const opts = { ...DEFAULTS, ...maybeOpts } @@ -153,6 +157,7 @@ export async function list ( onlyProjects: maybeOpts?.onlyProjects, registries: opts.registries, modulesDir: opts.modulesDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }) ) .map(async ([projectPath, dependenciesHierarchy]) => { diff --git a/reviewing/list/test/index.ts b/reviewing/list/test/index.ts index 6f5915ad1e8..70e9bcc8969 100644 --- a/reviewing/list/test/index.ts +++ b/reviewing/list/test/index.ts @@ -35,6 +35,7 @@ const fixtureWithAliasedDep = f.find('with-aliased-dep') test('list all deps of a package that has an external lockfile', async () => { expect(await list([fixtureWithExternalLockfile], { lockfileDir: path.join(fixtureWithExternalLockfile, '..'), + virtualStoreDirMaxLength: 120, })).toBe(`${LEGEND} ${boldHighlighted(`pkg@1.0.0 ${fixtureWithExternalLockfile}`)} @@ -49,6 +50,7 @@ test('print legend only once', async () => { path.join(workspaceWith2Pkgs, 'packages/foo'), ], { lockfileDir: workspaceWith2Pkgs, + virtualStoreDirMaxLength: 120, })).toBe(`${LEGEND} ${boldHighlighted(`bar@0.0.0 ${path.join(workspaceWith2Pkgs, 'packages/bar')}`)} @@ -68,6 +70,7 @@ test('list in workspace with private package', async () => { path.join(workspaceWithPrivatePkgs, 'packages/public'), ], { lockfileDir: workspaceWithPrivatePkgs, + virtualStoreDirMaxLength: 120, })).toBe(`${LEGEND} ${boldHighlighted(`private@1.0.0 ${path.join(workspaceWithPrivatePkgs, 'packages/private')} (PRIVATE)`)} @@ -82,7 +85,7 @@ is-positive ${VERSION_CLR('1.0.0')}`) }) test('list with default parameters', async () => { - expect(await list([fixture], { lockfileDir: fixture })).toBe(`${LEGEND} + expect(await list([fixture], { lockfileDir: fixture, virtualStoreDirMaxLength: 120 })).toBe(`${LEGEND} ${boldHighlighted(`fixture@1.0.0 ${fixture}`)} @@ -97,7 +100,7 @@ ${OPTIONAL_DEP_CLR('is-negative')} ${VERSION_CLR('2.1.0')}`) }) test('list with default parameters in pkg that has no name and version', async () => { - expect(await list([fixtureWithNoPkgNameAndNoVersion], { lockfileDir: fixtureWithNoPkgNameAndNoVersion })).toBe(`${LEGEND} + expect(await list([fixtureWithNoPkgNameAndNoVersion], { lockfileDir: fixtureWithNoPkgNameAndNoVersion, virtualStoreDirMaxLength: 120 })).toBe(`${LEGEND} ${boldHighlighted(fixtureWithNoPkgNameAndNoVersion)} @@ -112,7 +115,7 @@ ${OPTIONAL_DEP_CLR('is-negative')} ${VERSION_CLR('2.1.0')}`) }) test('list with default parameters in pkg that has no version', async () => { - expect(await list([fixtureWithNoPkgVersion], { lockfileDir: fixtureWithNoPkgVersion })).toBe(`${LEGEND} + expect(await list([fixtureWithNoPkgVersion], { lockfileDir: fixtureWithNoPkgVersion, virtualStoreDirMaxLength: 120 })).toBe(`${LEGEND} ${boldHighlighted(`fixture ${fixtureWithNoPkgVersion}`)} @@ -131,6 +134,7 @@ test('list dev only', async () => { await list([fixture], { include: { dependencies: false, devDependencies: true, optionalDependencies: false }, lockfileDir: fixture, + virtualStoreDirMaxLength: 120, }) ).toBe(`${LEGEND} @@ -146,6 +150,7 @@ test('list prod only', async () => { await list([fixture], { include: { dependencies: true, devDependencies: false, optionalDependencies: false }, lockfileDir: fixture, + virtualStoreDirMaxLength: 120, }) ).toBe(`${LEGEND} @@ -162,6 +167,7 @@ test('list prod only with depth 2', async () => { depth: 2, include: { dependencies: true, devDependencies: false, optionalDependencies: false }, lockfileDir: fixture, + virtualStoreDirMaxLength: 120, }) ).toBe(`${LEGEND} @@ -184,7 +190,7 @@ write-json-file ${VERSION_CLR('2.3.0')} }) test('list with depth 1', async () => { - expect(await list([fixture], { depth: 1, lockfileDir: fixture })).toBe(`${LEGEND} + expect(await list([fixture], { depth: 1, lockfileDir: fixture, virtualStoreDirMaxLength: 120 })).toBe(`${LEGEND} ${boldHighlighted(`fixture@1.0.0 ${fixture}`)} @@ -205,12 +211,12 @@ ${OPTIONAL_DEP_CLR('is-negative')} ${VERSION_CLR('2.1.0')}`) }) test('list with depth -1', async () => { - expect(await list([fixture], { depth: -1, lockfileDir: fixture })).toBe(`${boldHighlighted(`fixture@1.0.0 ${fixture}`)}`) + expect(await list([fixture], { depth: -1, lockfileDir: fixture, virtualStoreDirMaxLength: 120 })).toBe(`${boldHighlighted(`fixture@1.0.0 ${fixture}`)}`) }) test('list with depth 1 and selected packages', async () => { expect( - await listForPackages(['make-dir', 'pify@2', 'sort-keys@2', 'is-negative'], [fixture], { depth: 1, lockfileDir: fixture }) + await listForPackages(['make-dir', 'pify@2', 'sort-keys@2', 'is-negative'], [fixture], { depth: 1, lockfileDir: fixture, virtualStoreDirMaxLength: 120 }) ).toBe(`${LEGEND} ${boldHighlighted(`fixture@1.0.0 ${fixture}`)} @@ -226,7 +232,7 @@ ${highlighted(OPTIONAL_DEP_CLR('is-negative') + ' ' + VERSION_CLR('2.1.0'))}` }) test('list in long format', async () => { - expect(await list([fixture], { long: true, lockfileDir: fixture })).toBe(`${LEGEND} + expect(await list([fixture], { long: true, lockfileDir: fixture, virtualStoreDirMaxLength: 0 })).toBe(`${LEGEND} ${boldHighlighted(`fixture@1.0.0 ${fixture}`)} @@ -259,6 +265,7 @@ test('parseable list in workspace with private package', async () => { ], { reportAs: 'parseable', lockfileDir: workspaceWithPrivatePkgs, + virtualStoreDirMaxLength: 120, })).toBe(`${path.join(workspaceWithPrivatePkgs, 'packages/private')} ${path.join(workspaceWithPrivatePkgs, 'node_modules/.pnpm/is-positive@1.0.0/node_modules/is-positive')} ${path.join(workspaceWithPrivatePkgs, 'packages/public')}`) @@ -272,6 +279,7 @@ test('long parseable list in workspace with private package', async () => { reportAs: 'parseable', long: true, lockfileDir: workspaceWithPrivatePkgs, + virtualStoreDirMaxLength: 120, })).toBe(`${path.join(workspaceWithPrivatePkgs, 'packages/private')}:private@1.0.0:PRIVATE ${path.join(workspaceWithPrivatePkgs, 'node_modules/.pnpm/is-positive@1.0.0/node_modules/is-positive')}:is-positive@1.0.0 ${path.join(workspaceWithPrivatePkgs, 'packages/public')}:public@1.0.0`) @@ -284,6 +292,7 @@ test('JSON list in workspace with private package', async () => { ], { reportAs: 'json', lockfileDir: workspaceWithPrivatePkgs, + virtualStoreDirMaxLength: 120, })).toBe( JSON.stringify([ { @@ -319,7 +328,7 @@ test('JSON list in workspace with private package', async () => { }) test('parseable list with depth 1', async () => { - expect(await list([fixture], { reportAs: 'parseable', depth: 1, lockfileDir: fixture })).toBe(`${fixture} + expect(await list([fixture], { reportAs: 'parseable', depth: 1, lockfileDir: fixture, virtualStoreDirMaxLength: 120 })).toBe(`${fixture} ${path.join(fixture, 'node_modules/.pnpm/detect-indent@5.0.0/node_modules/detect-indent')} ${path.join(fixture, 'node_modules/.pnpm/graceful-fs@4.2.2/node_modules/graceful-fs')} ${path.join(fixture, 'node_modules/.pnpm/is-negative@2.1.0/node_modules/is-negative')} @@ -332,7 +341,7 @@ ${path.join(fixture, 'node_modules/.pnpm/write-json-file@2.3.0/node_modules/writ }) test('JSON list with depth 1', async () => { - expect(await list([fixture], { reportAs: 'json', depth: 1, lockfileDir: fixture })).toBe(JSON.stringify([{ + expect(await list([fixture], { reportAs: 'json', depth: 1, lockfileDir: fixture, virtualStoreDirMaxLength: 120 })).toBe(JSON.stringify([{ name: 'fixture', version: '1.0.0', path: fixture, @@ -414,7 +423,7 @@ test('JSON list with depth 1', async () => { test('JSON list with aliased dep', async () => { expect( - await list([fixtureWithAliasedDep], { reportAs: 'json', lockfileDir: fixtureWithAliasedDep }) + await list([fixtureWithAliasedDep], { reportAs: 'json', lockfileDir: fixtureWithAliasedDep, virtualStoreDirMaxLength: 120 }) ).toBe( JSON.stringify([ { @@ -434,7 +443,7 @@ test('JSON list with aliased dep', async () => { ], null, 2) ) expect( - await list([fixtureWithAliasedDep], { lockfileDir: fixtureWithAliasedDep, long: true, reportAs: 'json' }) + await list([fixtureWithAliasedDep], { lockfileDir: fixtureWithAliasedDep, long: true, reportAs: 'json', virtualStoreDirMaxLength: 120 }) ).toBe( JSON.stringify([{ name: 'with-aliased-dep', @@ -471,6 +480,7 @@ test('parseable list with depth 1 and dev only', async () => { include: { dependencies: false, devDependencies: true, optionalDependencies: false }, lockfileDir: fixture, reportAs: 'parseable', + virtualStoreDirMaxLength: 120, }) ).toBe(`${fixture} ${path.join(fixture, 'node_modules/.pnpm/is-positive@3.1.0/node_modules/is-positive')}` @@ -488,6 +498,7 @@ test('parseable list with depth 1 without unnecessary empty newlines', async () lockfileDir: workspaceWithDifferentDeps, depth: 1, reportAs: 'parseable', + virtualStoreDirMaxLength: 120, } )).toBe(`${path.join(workspaceWithDifferentDeps, 'packages/bar')} ${path.join(workspaceWithDifferentDeps, 'node_modules/.pnpm/is-positive@3.1.0/node_modules/is-positive')}` @@ -495,7 +506,7 @@ ${path.join(workspaceWithDifferentDeps, 'node_modules/.pnpm/is-positive@3.1.0/no }) test('long parseable list with depth 1', async () => { - expect(await list([fixture], { reportAs: 'parseable', depth: 1, lockfileDir: fixture, long: true })).toBe(`${fixture}:fixture@1.0.0 + expect(await list([fixture], { reportAs: 'parseable', depth: 1, lockfileDir: fixture, long: true, virtualStoreDirMaxLength: 120 })).toBe(`${fixture}:fixture@1.0.0 ${path.join(fixture, 'node_modules/.pnpm/detect-indent@5.0.0/node_modules/detect-indent')}:detect-indent@5.0.0 ${path.join(fixture, 'node_modules/.pnpm/graceful-fs@4.2.2/node_modules/graceful-fs')}:graceful-fs@4.2.2 ${path.join(fixture, 'node_modules/.pnpm/is-negative@2.1.0/node_modules/is-negative')}:is-negative@2.1.0 @@ -508,7 +519,7 @@ ${path.join(fixture, 'node_modules/.pnpm/write-json-file@2.3.0/node_modules/writ }) test('long parseable list with depth 1 when package has no version', async () => { - expect(await list([fixtureWithNoPkgVersion], { reportAs: 'parseable', depth: 1, lockfileDir: fixtureWithNoPkgVersion, long: true })).toBe(`\ + expect(await list([fixtureWithNoPkgVersion], { reportAs: 'parseable', depth: 1, lockfileDir: fixtureWithNoPkgVersion, long: true, virtualStoreDirMaxLength: 120 })).toBe(`\ ${fixtureWithNoPkgVersion}:fixture ${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/detect-indent@5.0.0/node_modules/detect-indent')}:detect-indent@5.0.0 ${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/graceful-fs@4.2.2/node_modules/graceful-fs')}:graceful-fs@4.2.2 @@ -525,7 +536,7 @@ test('long parseable list with depth 1 when package has no name and no version', expect( await list( [fixtureWithNoPkgNameAndNoVersion], - { reportAs: 'parseable', depth: 1, lockfileDir: fixtureWithNoPkgNameAndNoVersion, long: true } + { reportAs: 'parseable', depth: 1, lockfileDir: fixtureWithNoPkgNameAndNoVersion, long: true, virtualStoreDirMaxLength: 120 } ) ).toBe(`${fixtureWithNoPkgNameAndNoVersion} ${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/detect-indent@5.0.0/node_modules/detect-indent')}:detect-indent@5.0.0 @@ -541,11 +552,11 @@ ${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/write-json-fil }) test('print empty', async () => { - expect(await list([emptyFixture], { lockfileDir: emptyFixture })).toBe(`${LEGEND}\n\n${boldHighlighted(`empty@1.0.0 ${emptyFixture}`)}`) + expect(await list([emptyFixture], { lockfileDir: emptyFixture, virtualStoreDirMaxLength: 120 })).toBe(`${LEGEND}\n\n${boldHighlighted(`empty@1.0.0 ${emptyFixture}`)}`) }) test("don't print empty", async () => { - expect(await list([emptyFixture], { alwaysPrintRootPackage: false, lockfileDir: emptyFixture })).toBe('') + expect(await list([emptyFixture], { alwaysPrintRootPackage: false, lockfileDir: emptyFixture, virtualStoreDirMaxLength: 120 })).toBe('') }) test('unsaved dependencies are marked', async () => { @@ -783,7 +794,7 @@ foo ${VERSION_CLR('1.0.0')} test('peer dependencies are marked', async () => { const fixture = f.find('with-peer') - const output = await list([fixture], { depth: 1, lockfileDir: fixture }) + const output = await list([fixture], { depth: 1, lockfileDir: fixture, virtualStoreDirMaxLength: 120 }) expect(output).toBe(`${LEGEND} ${boldHighlighted(`with-peer@1.0.0 ${fixture}`)} @@ -800,7 +811,7 @@ ajv-keywords ${VERSION_CLR('3.4.1')} test('peer dependencies are marked when searching', async () => { const fixture = f.find('with-peer') - const output = await listForPackages(['ajv'], [fixture], { depth: 1, lockfileDir: fixture }) + const output = await listForPackages(['ajv'], [fixture], { depth: 1, lockfileDir: fixture, virtualStoreDirMaxLength: 120 }) expect(output).toBe(`${LEGEND} ${boldHighlighted(`with-peer@1.0.0 ${fixture}`)} @@ -813,7 +824,7 @@ ajv-keywords ${VERSION_CLR('3.4.1')} test('--only-projects shows only projects', async () => { const fixture = f.find('workspace-with-nested-workspace-deps') - const output = await list([fixture], { depth: 999, lockfileDir: fixture, onlyProjects: true }) + const output = await list([fixture], { depth: 999, lockfileDir: fixture, onlyProjects: true, virtualStoreDirMaxLength: 120 }) // The "workspace-with-nested-workspace-deps" test case has an external // dependency under @scope/b, but that package should not be printed when diff --git a/reviewing/plugin-commands-licenses/src/licensesList.ts b/reviewing/plugin-commands-licenses/src/licensesList.ts index 5f85ff9a569..465d8057949 100644 --- a/reviewing/plugin-commands-licenses/src/licensesList.ts +++ b/reviewing/plugin-commands-licenses/src/licensesList.ts @@ -28,6 +28,7 @@ Config, | 'selectedProjectsGraph' | 'rootProjectManifest' | 'rootProjectManifestDir' +| 'virtualStoreDirMaxLength' > & Partial> @@ -66,6 +67,7 @@ export async function licensesList (opts: LicensesCommandOptions): Promise & Partial> & { alwaysPrintRootPackage?: boolean depth?: number @@ -166,6 +167,7 @@ export async function render ( onlyProjects?: boolean parseable?: boolean modulesDir?: string + virtualStoreDirMaxLength: number } ): Promise { const listOpts = { @@ -178,6 +180,7 @@ export async function render ( reportAs: (opts.parseable ? 'parseable' : (opts.json ? 'json' : 'tree')) as ('parseable' | 'json' | 'tree'), showExtraneous: false, modulesDir: opts.modulesDir, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, } return (params.length > 0) ? listForPackages(params, prefixes, listOpts) diff --git a/reviewing/plugin-commands-listing/src/recursive.ts b/reviewing/plugin-commands-listing/src/recursive.ts index 2a979052b2c..a3933aa55f7 100644 --- a/reviewing/plugin-commands-listing/src/recursive.ts +++ b/reviewing/plugin-commands-listing/src/recursive.ts @@ -8,7 +8,7 @@ import { render } from './list' export async function listRecursive ( pkgs: Project[], params: string[], - opts: Pick & { + opts: Pick & { depth?: number include: IncludedDependencies long?: boolean diff --git a/reviewing/plugin-commands-listing/test/index.ts b/reviewing/plugin-commands-listing/test/index.ts index fdf248bc3aa..babf699621b 100644 --- a/reviewing/plugin-commands-listing/test/index.ts +++ b/reviewing/plugin-commands-listing/test/index.ts @@ -28,6 +28,7 @@ test('listing packages', async () => { dev: false, dir: process.cwd(), optional: false, + virtualStoreDirMaxLength: 120, }, []) expect(stripAnsi(output)).toBe(`Legend: production dependency, optional only, dev only @@ -43,6 +44,7 @@ is-positive 1.0.0`) dir: process.cwd(), optional: false, production: false, + virtualStoreDirMaxLength: 120, }, []) expect(stripAnsi(output)).toBe(`Legend: production dependency, optional only, dev only @@ -56,6 +58,7 @@ is-negative 1.0.0`) { const output = await list.handler({ dir: process.cwd(), + virtualStoreDirMaxLength: 120, }, []) expect(stripAnsi(output)).toBe(`Legend: production dependency, optional only, dev only @@ -92,6 +95,7 @@ test(`listing packages of a project that has an external ${WANTED_LOCKFILE}`, as const output = await list.handler({ dir: process.cwd(), lockfileDir: path.resolve('..'), + virtualStoreDirMaxLength: 120, }, []) expect(stripAnsi(output)).toBe(`Legend: production dependency, optional only, dev only @@ -113,6 +117,7 @@ test.skip('list on a project with skipped optional dependencies', async () => { const output = await list.handler({ depth: 10, dir: process.cwd(), + virtualStoreDirMaxLength: 120, }, []) expect(stripAnsi(output)).toBe(`Legend: production dependency, optional only, dev only @@ -129,6 +134,7 @@ pkg-with-optional 1.0.0 const output = await list.handler({ depth: 10, dir: process.cwd(), + virtualStoreDirMaxLength: 120, }, ['not-compatible-with-any-os']) expect(stripAnsi(output)).toBe(`Legend: production dependency, optional only, dev only @@ -143,6 +149,7 @@ pkg-with-optional 1.0.0 { const output = await why.handler({ dir: process.cwd(), + virtualStoreDirMaxLength: 120, }, ['not-compatible-with-any-os']) expect(stripAnsi(output)).toBe(`Legend: production dependency, optional only, dev only @@ -179,6 +186,7 @@ test('listing packages should not fail on package that has local file directory dev: false, dir: pkgDir, optional: false, + virtualStoreDirMaxLength: 120, }, []) expect(stripAnsi(output)).toBe(`Legend: production dependency, optional only, dev only diff --git a/reviewing/plugin-commands-listing/test/utils/index.ts b/reviewing/plugin-commands-listing/test/utils/index.ts index 6a46b3bec3a..82a3f646919 100644 --- a/reviewing/plugin-commands-listing/test/utils/index.ts +++ b/reviewing/plugin-commands-listing/test/utils/index.ts @@ -47,4 +47,5 @@ export const DEFAULT_OPTS = { useRunningStoreServer: false, useStoreServer: false, workspaceConcurrency: 4, + virtualStoreDirMaxLength: 120, } diff --git a/reviewing/plugin-commands-listing/test/why.ts b/reviewing/plugin-commands-listing/test/why.ts index 8f51d083c74..82b2f1eabee 100644 --- a/reviewing/plugin-commands-listing/test/why.ts +++ b/reviewing/plugin-commands-listing/test/why.ts @@ -15,6 +15,7 @@ test('`pnpm why` should fail if no package name was provided', async () => { try { await why.handler({ dir: process.cwd(), + virtualStoreDirMaxLength: 120, }, []) } catch (_err: any) { // eslint-disable-line err = _err @@ -38,6 +39,7 @@ test('"why" should find non-direct dependency', async () => { dev: false, dir: process.cwd(), optional: false, + virtualStoreDirMaxLength: 120, }, ['@pnpm.e2e/dep-of-pkg-with-1-dep']) expect(stripAnsi(output)).toBe(`Legend: production dependency, optional only, dev only diff --git a/reviewing/plugin-commands-outdated/test/utils/index.ts b/reviewing/plugin-commands-outdated/test/utils/index.ts index c9af8cafd7e..fa796c132f4 100644 --- a/reviewing/plugin-commands-outdated/test/utils/index.ts +++ b/reviewing/plugin-commands-outdated/test/utils/index.ts @@ -51,4 +51,5 @@ export const DEFAULT_OPTS = { useRunningStoreServer: false, useStoreServer: false, workspaceConcurrency: 4, + virtualStoreDirMaxLength: 120, } diff --git a/store/package-store/src/storeController/index.ts b/store/package-store/src/storeController/index.ts index 64feaec235c..d8d93cfc818 100644 --- a/store/package-store/src/storeController/index.ts +++ b/store/package-store/src/storeController/index.ts @@ -27,6 +27,7 @@ export function createPackageStore ( networkConcurrency?: number packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone' | 'clone-or-copy' verifyStoreIntegrity: boolean + virtualStoreDirMaxLength: number } ): StoreController { const storeDir = initOpts.storeDir @@ -46,6 +47,7 @@ export function createPackageStore ( networkConcurrency: initOpts.networkConcurrency, storeDir: initOpts.storeDir, verifyStoreIntegrity: initOpts.verifyStoreIntegrity, + virtualStoreDirMaxLength: initOpts.virtualStoreDirMaxLength, }) return { diff --git a/store/package-store/test/index.ts b/store/package-store/test/index.ts index c051a61ed69..80c12ed925b 100644 --- a/store/package-store/test/index.ts +++ b/store/package-store/test/index.ts @@ -21,6 +21,7 @@ describe('store.importPackage()', () => { storeDir, cacheDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const pkgId = 'registry.npmjs.org/is-positive/1.0.0' const fetchResponse = (storeController.fetchPackage as FetchPackageToStoreFunction)({ @@ -59,6 +60,7 @@ describe('store.importPackage()', () => { storeDir, cacheDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) const pkgId = 'registry.npmjs.org/is-positive/1.0.0' const fetchResponse = (storeController.fetchPackage as FetchPackageToStoreFunction)({ diff --git a/store/plugin-commands-store/src/storeStatus/extendStoreStatusOptions.ts b/store/plugin-commands-store/src/storeStatus/extendStoreStatusOptions.ts index 30d2fc737da..a30e0fcb2a4 100644 --- a/store/plugin-commands-store/src/storeStatus/extendStoreStatusOptions.ts +++ b/store/plugin-commands-store/src/storeStatus/extendStoreStatusOptions.ts @@ -20,10 +20,11 @@ export interface StrictStoreStatusOptions { development: boolean optional: boolean binsDir: string + virtualStoreDirMaxLength: number } export type StoreStatusOptions = Partial & -Pick +Pick const defaults = async (opts: StoreStatusOptions): Promise => { const dir = opts.dir ?? process.cwd() diff --git a/store/plugin-commands-store/src/storeStatus/index.ts b/store/plugin-commands-store/src/storeStatus/index.ts index 5ffb78f7959..9f0928ccc9d 100644 --- a/store/plugin-commands-store/src/storeStatus/index.ts +++ b/store/plugin-commands-store/src/storeStatus/index.ts @@ -50,9 +50,9 @@ export async function storeStatus (maybeOpts: StoreStatusOptions): Promise { const pkgIndexFilePath = integrity ? getFilePathInCafs(cafsDir, integrity, 'index') - : path.join(storeDir, dp.depPathToFilename(id), 'integrity.json') + : path.join(storeDir, dp.depPathToFilename(id, maybeOpts.virtualStoreDirMaxLength), 'integrity.json') const { files } = await loadJsonFile(pkgIndexFilePath) - return (await dint.check(path.join(virtualStoreDir, dp.depPathToFilename(depPath), 'node_modules', name), files)) === false + return (await dint.check(path.join(virtualStoreDir, dp.depPathToFilename(depPath, maybeOpts.virtualStoreDirMaxLength), 'node_modules', name), files)) === false }, { concurrency: 8 }) if ((reporter != null) && typeof reporter === 'function') { diff --git a/store/plugin-commands-store/test/storeAdd.ts b/store/plugin-commands-store/test/storeAdd.ts index 44f0cc88cc1..73a75e071b4 100644 --- a/store/plugin-commands-store/test/storeAdd.ts +++ b/store/plugin-commands-store/test/storeAdd.ts @@ -24,6 +24,7 @@ test('pnpm store add express@4.16.3', async () => { storeDir, userConfig: {}, dlxCacheMaxAge: 0, + virtualStoreDirMaxLength: 120, }, ['add', 'express@4.16.3']) const { cafsHas } = assertStore(path.join(storeDir, STORE_VERSION)) @@ -50,6 +51,7 @@ test('pnpm store add scoped package that uses not the standard registry', async storeDir, userConfig: {}, dlxCacheMaxAge: 0, + virtualStoreDirMaxLength: 120, }, ['add', '@foo/no-deps@1.0.0']) const { cafsHas } = assertStore(path.join(storeDir, STORE_VERSION)) @@ -79,6 +81,7 @@ test('should fail if some packages can not be added', async () => { storeDir, userConfig: {}, dlxCacheMaxAge: 0, + virtualStoreDirMaxLength: 120, }, ['add', '@pnpm/this-does-not-exist']) } catch (e: any) { // eslint-disable-line thrown = true diff --git a/store/plugin-commands-store/test/storePath.ts b/store/plugin-commands-store/test/storePath.ts index 9062e1cc774..422d45d50c6 100644 --- a/store/plugin-commands-store/test/storePath.ts +++ b/store/plugin-commands-store/test/storePath.ts @@ -20,6 +20,7 @@ test('CLI prints the current store path', async () => { storeDir: '/home/example/.pnpm-store', userConfig: {}, dlxCacheMaxAge: 0, + virtualStoreDirMaxLength: 120, }, ['path']) const expectedStorePath = os.platform() === 'win32' diff --git a/store/plugin-commands-store/test/storePrune.ts b/store/plugin-commands-store/test/storePrune.ts index e0276db4e20..36311f885d8 100644 --- a/store/plugin-commands-store/test/storePrune.ts +++ b/store/plugin-commands-store/test/storePrune.ts @@ -49,6 +49,7 @@ test('remove unreferenced packages', async () => { storeDir, userConfig: {}, dlxCacheMaxAge: Infinity, + virtualStoreDirMaxLength: 120, }, ['prune']) expect(reporter).toHaveBeenCalledWith( @@ -73,6 +74,7 @@ test('remove unreferenced packages', async () => { storeDir, userConfig: {}, dlxCacheMaxAge: Infinity, + virtualStoreDirMaxLength: 120, }, ['prune']) expect(reporter).not.toHaveBeenCalledWith( @@ -109,6 +111,7 @@ test.skip('remove packages that are used by project that no longer exist', async storeDir, userConfig: {}, dlxCacheMaxAge: Infinity, + virtualStoreDirMaxLength: 120, }, ['prune']) expect(reporter).toHaveBeenCalledWith( @@ -148,6 +151,7 @@ test('keep dependencies used by others', async () => { storeDir, userConfig: {}, dlxCacheMaxAge: Infinity, + virtualStoreDirMaxLength: 120, }, ['prune']) project.storeHasNot('camelcase-keys', '3.0.0') @@ -173,6 +177,7 @@ test('keep dependency used by package', async () => { storeDir, userConfig: {}, dlxCacheMaxAge: Infinity, + virtualStoreDirMaxLength: 120, }, ['prune']) project.storeHas('is-positive', '3.1.0') @@ -196,6 +201,7 @@ test('prune will skip scanning non-directory in storeDir', async () => { storeDir, userConfig: {}, dlxCacheMaxAge: Infinity, + virtualStoreDirMaxLength: 120, }, ['prune']) }) @@ -223,6 +229,7 @@ test('prune does not fail if the store contains an unexpected directory', async storeDir, userConfig: {}, dlxCacheMaxAge: Infinity, + virtualStoreDirMaxLength: 120, }, ['prune']) expect(reporter).toHaveBeenCalledWith( @@ -261,6 +268,7 @@ test('prune removes alien files from the store if the --force flag is used', asy userConfig: {}, force: true, dlxCacheMaxAge: Infinity, + virtualStoreDirMaxLength: 120, }, ['prune']) expect(reporter).toHaveBeenCalledWith( expect.objectContaining({ @@ -326,6 +334,7 @@ test('prune removes cache directories that outlives dlx-cache-max-age', async () storeDir, userConfig: {}, dlxCacheMaxAge: 7, + virtualStoreDirMaxLength: 120, }, ['prune']) expect( diff --git a/store/plugin-commands-store/test/storeStatus.ts b/store/plugin-commands-store/test/storeStatus.ts index c219e88eea5..6684510f39d 100644 --- a/store/plugin-commands-store/test/storeStatus.ts +++ b/store/plugin-commands-store/test/storeStatus.ts @@ -41,6 +41,7 @@ test('CLI fails when store status finds modified packages', async () => { storeDir, userConfig: {}, dlxCacheMaxAge: 0, + virtualStoreDirMaxLength: 120, }, ['status']) } catch (_err: any) { // eslint-disable-line err = _err @@ -93,5 +94,6 @@ test('CLI does not fail when store status does not find modified packages', asyn storeDir, userConfig: {}, dlxCacheMaxAge: 0, + virtualStoreDirMaxLength: 120, }, ['status']) }) diff --git a/store/server/test/index.ts b/store/server/test/index.ts index 3503988ec2b..6f12ad5ece1 100644 --- a/store/server/test/index.ts +++ b/store/server/test/index.ts @@ -30,6 +30,7 @@ async function createStoreController (storeDir?: string) { cacheDir, storeDir, verifyStoreIntegrity: true, + virtualStoreDirMaxLength: 120, }) } diff --git a/store/store-connection-manager/src/createNewStoreController.ts b/store/store-connection-manager/src/createNewStoreController.ts index 1615eb6d467..aecea56c21d 100644 --- a/store/store-connection-manager/src/createNewStoreController.ts +++ b/store/store-connection-manager/src/createNewStoreController.ts @@ -41,6 +41,7 @@ export type CreateNewStoreControllerOptions = CreateResolverOptions & Pick & { cafsLocker?: CafsLocker ignoreFile?: (filename: string) => boolean @@ -105,6 +106,7 @@ export async function createNewStoreController ( verifyStoreIntegrity: typeof opts.verifyStoreIntegrity === 'boolean' ? opts.verifyStoreIntegrity : true, + virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength, }), dir: opts.storeDir, }