mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 07:38:12 -05:00
feat: configurable max length of directories inside node_modules/.pnpm (#7994)
close #7355
This commit is contained in:
37
.changeset/old-cars-notice.md
Normal file
37
.changeset/old-cars-notice.md
Normal file
@@ -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).
|
||||
@@ -192,6 +192,7 @@ export interface Config {
|
||||
dedupeInjectedDeps?: boolean
|
||||
nodeOptions?: string
|
||||
packageManagerStrict?: boolean
|
||||
virtualStoreDirMaxLength: number
|
||||
}
|
||||
|
||||
export interface ConfigWithDeprecatedSettings extends Config {
|
||||
|
||||
@@ -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)
|
||||
|
||||
7
deps/graph-builder/src/lockfileToDepGraph.ts
vendored
7
deps/graph-builder/src/lockfileToDepGraph.ts
vendored
@@ -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<string> | 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))) {
|
||||
|
||||
@@ -47,6 +47,7 @@ export type StrictRebuildOptions = {
|
||||
deployAllFiles: boolean
|
||||
neverBuiltDependencies?: string[]
|
||||
onlyBuiltDependencies?: string[]
|
||||
virtualStoreDirMaxLength: number
|
||||
} & Pick<Config, 'sslConfigs'>
|
||||
|
||||
export type RebuildOptions = Partial<StrictRebuildOptions> &
|
||||
|
||||
@@ -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 })
|
||||
}))
|
||||
|
||||
@@ -52,4 +52,5 @@ export const DEFAULT_OPTS = {
|
||||
cpu: ['current'],
|
||||
libc: ['current'],
|
||||
},
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ export async function audit (
|
||||
registry: string
|
||||
retry?: RetryTimeoutOptions
|
||||
timeout?: number
|
||||
virtualStoreDirMaxLength: number
|
||||
}
|
||||
): Promise<AuditReport> {
|
||||
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<AuditReport> {
|
||||
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
|
||||
|
||||
@@ -164,6 +164,7 @@ describe('audit', () => {
|
||||
retry: {
|
||||
retries: 0,
|
||||
},
|
||||
virtualStoreDirMaxLength: 120,
|
||||
})
|
||||
} catch (_err: any) { // eslint-disable-line
|
||||
err = _err
|
||||
|
||||
@@ -15,6 +15,7 @@ export async function writePnpFile (
|
||||
importerNames: Record<string, string>
|
||||
lockfileDir: string
|
||||
virtualStoreDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
registries: Registries
|
||||
}
|
||||
): Promise<void> {
|
||||
@@ -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
|
||||
)))
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -12,11 +12,12 @@ export function extendProjectsWithTargetDirs<T> (
|
||||
ctx: {
|
||||
virtualStoreDir: string
|
||||
pkgLocationsByDepPath?: Record<string, string[]>
|
||||
virtualStoreDirMaxLength: number
|
||||
}
|
||||
): Array<T & { id: string, stages: string[], targetDirs: string[] }> {
|
||||
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<string, T & { id: string, targetDirs: string[], stages?: string[] }> =
|
||||
Object.fromEntries(projects.map((project) => [project.id, { ...project, targetDirs: [] as string[] }]))
|
||||
Object.entries(lockfile.packages ?? {})
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"/)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<string, DirEntry> {
|
||||
for (const [depPath, pkgSnapshot] of Object.entries(lockfile.packages ?? {})) {
|
||||
const { name } = nameVerFromPkgSnapshot(depPath, pkgSnapshot)
|
||||
const pkgNodeModules = {} as Record<string, DirEntry>
|
||||
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<string, DirEntry> {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -27,6 +27,7 @@ const basePatchOption = {
|
||||
registries: { default: `http://localhost:${REGISTRY_MOCK_PORT}/` },
|
||||
userConfig: {},
|
||||
virtualStoreDir: 'node_modules/.pnpm',
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
describe('patch and commit', () => {
|
||||
|
||||
@@ -53,4 +53,5 @@ export const DEFAULT_OPTS = {
|
||||
cpu: ['current'],
|
||||
libc: ['current'],
|
||||
},
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ export type ListMissingPeersOptions = Partial<GetContextOptions>
|
||||
>
|
||||
& Partial<Pick<InstallOptions, 'supportedArchitectures'>>
|
||||
& Pick<GetContextOptions, 'autoInstallPeers' | 'excludeLinksFromLockfile' | 'storeDir'>
|
||||
& Required<Pick<InstallOptions, 'virtualStoreDirMaxLength'>>
|
||||
|
||||
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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -68,6 +68,7 @@ export interface LinkPackagesOptions {
|
||||
skipped: Set<string>
|
||||
storeController: StoreController
|
||||
virtualStoreDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
wantedLockfile: Lockfile
|
||||
wantedToBeSkippedPackageIds: Set<string>
|
||||
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 !== '.') {
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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'))
|
||||
|
||||
|
||||
17
pkg-manager/core/test/install/virtualStoreDirMaxLength.ts
Normal file
17
pkg-manager/core/test/install/virtualStoreDirMaxLength.ts
Normal file
@@ -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)
|
||||
}
|
||||
})
|
||||
@@ -52,6 +52,7 @@ export interface PnpmContext {
|
||||
publicHoistPattern: string[] | undefined
|
||||
lockfileDir: string
|
||||
virtualStoreDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
skipped: Set<string>
|
||||
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,
|
||||
|
||||
@@ -20,6 +20,7 @@ const DEFAULT_OPTIONS: GetContextOptions = {
|
||||
optionalDependencies: true,
|
||||
},
|
||||
storeDir: path.join(__dirname, 'store'),
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
test('getContext - extendNodePath false', async () => {
|
||||
|
||||
@@ -129,6 +129,7 @@ export interface HeadlessOptions {
|
||||
lockfileDir: string
|
||||
modulesDir?: string
|
||||
virtualStoreDir?: string
|
||||
virtualStoreDirMaxLength: number
|
||||
patchedDependencies?: Record<string, PatchFile>
|
||||
scriptsPrependNodePath?: boolean | 'warn-only'
|
||||
scriptShell?: string
|
||||
@@ -248,6 +249,7 @@ export async function headlessInstall (opts: HeadlessOptions): Promise<Installat
|
||||
skipped,
|
||||
storeController: opts.storeController,
|
||||
virtualStoreDir,
|
||||
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
||||
wantedLockfile: filterLockfileByEngine(wantedLockfile, filterOpts).lockfile,
|
||||
}
|
||||
)
|
||||
@@ -338,6 +340,7 @@ export async function headlessInstall (opts: HeadlessOptions): Promise<Installat
|
||||
importerNames,
|
||||
lockfileDir,
|
||||
virtualStoreDir,
|
||||
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
||||
registries: opts.registries,
|
||||
})
|
||||
}
|
||||
@@ -424,6 +427,7 @@ export async function headlessInstall (opts: HeadlessOptions): Promise<Installat
|
||||
publicHoistedModulesDir,
|
||||
publicHoistPattern: opts.publicHoistPattern ?? [],
|
||||
virtualStoreDir,
|
||||
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
||||
hoistedWorkspacePackages: opts.hoistWorkspacePackages
|
||||
? Object.values(opts.allProjects).reduce((hoistedWorkspacePackages, project) => {
|
||||
if (project.manifest.name && project.id !== '.') {
|
||||
@@ -531,6 +535,7 @@ export async function headlessInstall (opts: HeadlessOptions): Promise<Installat
|
||||
const projectsToBeBuilt = extendProjectsWithTargetDirs(selectedProjects, wantedLockfile, {
|
||||
pkgLocationsByDepPath,
|
||||
virtualStoreDir,
|
||||
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
||||
})
|
||||
|
||||
if (opts.enableModulesDir !== false) {
|
||||
@@ -598,6 +603,7 @@ export async function headlessInstall (opts: HeadlessOptions): Promise<Installat
|
||||
skipped: Array.from(skipped),
|
||||
storeDir: opts.storeDir,
|
||||
virtualStoreDir,
|
||||
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
||||
}, {
|
||||
makeModulesDir: Object.keys(filteredLockfile.packages ?? {}).length > 0,
|
||||
})
|
||||
|
||||
@@ -24,6 +24,7 @@ export interface HoistOpts extends GetHoistedDependenciesOpts {
|
||||
extraNodePath?: string[]
|
||||
preferSymlinkedExecutables?: boolean
|
||||
virtualStoreDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
}
|
||||
|
||||
export async function hoist (opts: HoistOpts): Promise<HoistedDependencies> {
|
||||
@@ -36,6 +37,7 @@ export async function hoist (opts: HoistOpts): Promise<HoistedDependencies> {
|
||||
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<string, HoistedWorkspaceProject>
|
||||
}
|
||||
): Promise<void> {
|
||||
@@ -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]) {
|
||||
|
||||
@@ -49,6 +49,7 @@ export async function prune (
|
||||
pruneVirtualStore?: boolean
|
||||
skipped: Set<string>
|
||||
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<string>(['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(
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface Modules {
|
||||
skipped: string[]
|
||||
storeDir: string
|
||||
virtualStoreDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
injectedDeps?: Record<string, string[]>
|
||||
hoistedLocations?: Record<string, string[]>
|
||||
}
|
||||
@@ -80,6 +81,9 @@ export async function readModulesManifest (modulesDir: string): Promise<Modules
|
||||
if (!modules.prunedAt) {
|
||||
modules.prunedAt = new Date().toUTCString()
|
||||
}
|
||||
if (!modules.virtualStoreDirMaxLength) {
|
||||
modules.virtualStoreDirMaxLength = 120
|
||||
}
|
||||
return modules
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ test('writeModulesManifest() and readModulesManifest()', async () => {
|
||||
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)
|
||||
|
||||
@@ -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<FetchPackageToStoreOptions, 'pkg' | 'ignoreScripts'>
|
||||
) {
|
||||
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
|
||||
): {
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -32,6 +32,7 @@ const DEFAULT_OPTIONS = {
|
||||
sort: true,
|
||||
userConfig: {},
|
||||
workspaceConcurrency: 1,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
test('fetch dependencies', async () => {
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -40,6 +40,7 @@ const DEFAULT_OPTS = {
|
||||
userConfig: {},
|
||||
useRunningStoreServer: false,
|
||||
useStoreServer: false,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
test('import from package-lock.json', async () => {
|
||||
|
||||
@@ -38,6 +38,7 @@ const DEFAULT_OPTS = {
|
||||
userConfig: {},
|
||||
useRunningStoreServer: false,
|
||||
useStoreServer: false,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
test('import from shared yarn.lock of monorepo', async () => {
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -41,6 +41,7 @@ const DEFAULT_OPTIONS = {
|
||||
sort: true,
|
||||
userConfig: {},
|
||||
workspaceConcurrency: 1,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
test('interactively update', async () => {
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -49,4 +49,5 @@ export const DEFAULT_OPTS = {
|
||||
useRunningStoreServer: false,
|
||||
useStoreServer: false,
|
||||
workspaceConcurrency: 4,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ export async function readProjectsContext<T> (
|
||||
registries: Registries | null | undefined
|
||||
rootModulesDir: string
|
||||
skipped: Set<string>
|
||||
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<T> (
|
||||
registries: ((modules?.registries) != null) ? normalizeRegistries(modules.registries) : undefined,
|
||||
rootModulesDir,
|
||||
skipped: new Set(modules?.skipped ?? []),
|
||||
virtualStoreDirMaxLength: modules?.virtualStoreDirMaxLength,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +197,7 @@ export async function resolveDependencies (
|
||||
lockfileDir: opts.lockfileDir,
|
||||
projects: projectsToLink,
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
||||
resolvePeersFromWorkspaceRoot: Boolean(opts.resolvePeersFromWorkspaceRoot),
|
||||
resolvedImporters,
|
||||
})
|
||||
|
||||
@@ -164,6 +164,7 @@ export interface ResolutionContext {
|
||||
registries: Registries
|
||||
resolutionMode?: 'highest' | 'time-based' | 'lowest-direct'
|
||||
virtualStoreDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
workspacePackages?: WorkspacePackages
|
||||
missingPeersOfChildrenByPkgId: Record<string, { parentImporterId: string, missingPeersOfChildren: MissingPeersOfChildren }>
|
||||
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'
|
||||
|
||||
@@ -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<T> (
|
||||
skipped: wantedToBeSkippedPackageIds,
|
||||
storeController: opts.storeController,
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
||||
wantedLockfile: opts.wantedLockfile,
|
||||
appliedPatches: new Set<string>(),
|
||||
updatedSet: new Set<string>(),
|
||||
|
||||
@@ -69,6 +69,7 @@ export async function resolvePeers<T extends PartialResolvedPackage> (
|
||||
projects: ProjectToResolve[]
|
||||
dependenciesTree: DependenciesTree<T>
|
||||
virtualStoreDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
lockfileDir: string
|
||||
resolvePeersFromWorkspaceRoot?: boolean
|
||||
dedupePeerDependents?: boolean
|
||||
@@ -114,6 +115,7 @@ export async function resolvePeers<T extends PartialResolvedPackage> (
|
||||
purePkgs: new Set(),
|
||||
rootDir,
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
||||
})
|
||||
if (finishing) {
|
||||
finishingList.push(finishing)
|
||||
@@ -312,6 +314,7 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
dependenciesTree: DependenciesTree<T>
|
||||
depGraph: GenericDependenciesGraph<T>
|
||||
virtualStoreDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
peerDependencyIssues: Pick<PeerDependencyIssues, 'bad' | 'missing'>
|
||||
peersCache: PeersCache
|
||||
purePkgs: Set<string> // pure packages are those that don't rely on externally resolved peers
|
||||
@@ -510,7 +513,7 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
}
|
||||
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<string>()
|
||||
@@ -584,6 +587,7 @@ async function resolvePeersOfChildren<T extends PartialResolvedPackage> (
|
||||
peerDependencyIssues: Pick<PeerDependencyIssues, 'bad' | 'missing'>
|
||||
peersCache: PeersCache
|
||||
virtualStoreDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
purePkgs: Set<string>
|
||||
depGraph: GenericDependenciesGraph<T>
|
||||
dependenciesTree: DependenciesTree<T>
|
||||
|
||||
@@ -96,6 +96,7 @@ test('packages are not deduplicated when versions do not match', async () => {
|
||||
} as DependenciesTreeNode<PartialResolvedPackage>])),
|
||||
dedupePeerDependents: true,
|
||||
virtualStoreDir: '',
|
||||
virtualStoreDirMaxLength: 120,
|
||||
lockfileDir: '',
|
||||
})
|
||||
|
||||
|
||||
@@ -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([
|
||||
|
||||
@@ -49,4 +49,5 @@ export const DEFAULT_OPTS = {
|
||||
useRunningStoreServer: false,
|
||||
useStoreServer: false,
|
||||
workspaceConcurrency: 4,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
@@ -45,4 +45,5 @@ export const DEFAULT_OPTS = {
|
||||
useRunningStoreServer: false,
|
||||
useStoreServer: false,
|
||||
workspaceConcurrency: 4,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
@@ -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<DependenciesHierarchy> {
|
||||
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)
|
||||
|
||||
@@ -22,6 +22,7 @@ export interface GetPkgInfoOpts {
|
||||
readonly skipped: Set<string>
|
||||
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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]: {
|
||||
|
||||
@@ -220,6 +220,13 @@ export type ReadPackageIndexFileResult =
|
||||
| { local: false, files: Record<string, PackageFileInfo> }
|
||||
| { local: true, files: Record<string, string> }
|
||||
|
||||
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<ReadPackageIndexFileResult> {
|
||||
// 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
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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\'')
|
||||
|
||||
@@ -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([
|
||||
|
||||
@@ -64,6 +64,7 @@ export async function searchForPackages (
|
||||
onlyProjects?: boolean
|
||||
registries?: Registries
|
||||
modulesDir?: string
|
||||
virtualStoreDirMaxLength: number
|
||||
}
|
||||
): Promise<PackageDependencyHierarchy[]> {
|
||||
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<string> {
|
||||
const opts = { ...DEFAULTS, ...maybeOpts }
|
||||
@@ -135,6 +138,7 @@ export async function list (
|
||||
registries?: Registries
|
||||
showExtraneous?: boolean
|
||||
modulesDir?: string
|
||||
virtualStoreDirMaxLength: number
|
||||
}
|
||||
): Promise<string> {
|
||||
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]) => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,6 +28,7 @@ Config,
|
||||
| 'selectedProjectsGraph'
|
||||
| 'rootProjectManifest'
|
||||
| 'rootProjectManifestDir'
|
||||
| 'virtualStoreDirMaxLength'
|
||||
> &
|
||||
Partial<Pick<Config, 'userConfig'>>
|
||||
|
||||
@@ -66,6 +67,7 @@ export async function licensesList (opts: LicensesCommandOptions): Promise<Licen
|
||||
lockfileDir: opts.lockfileDir ?? opts.dir,
|
||||
storeDir,
|
||||
virtualStoreDir: opts.virtualStoreDir ?? '.',
|
||||
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
||||
modulesDir: opts.modulesDir,
|
||||
registries: opts.registries,
|
||||
wantedLockfile: lockfile,
|
||||
|
||||
@@ -47,4 +47,5 @@ export const DEFAULT_OPTS = {
|
||||
useStoreServer: false,
|
||||
virtualStoreDir: 'node_modules/.pnpm',
|
||||
workspaceConcurrency: 4,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ export type ListCommandOptions = Pick<Config,
|
||||
| 'production'
|
||||
| 'selectedProjectsGraph'
|
||||
| 'modulesDir'
|
||||
| 'virtualStoreDirMaxLength'
|
||||
> & Partial<Pick<Config, 'cliOptions'>> & {
|
||||
alwaysPrintRootPackage?: boolean
|
||||
depth?: number
|
||||
@@ -166,6 +167,7 @@ export async function render (
|
||||
onlyProjects?: boolean
|
||||
parseable?: boolean
|
||||
modulesDir?: string
|
||||
virtualStoreDirMaxLength: number
|
||||
}
|
||||
): Promise<string> {
|
||||
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)
|
||||
|
||||
@@ -8,7 +8,7 @@ import { render } from './list'
|
||||
export async function listRecursive (
|
||||
pkgs: Project[],
|
||||
params: string[],
|
||||
opts: Pick<Config, 'lockfileDir'> & {
|
||||
opts: Pick<Config, 'lockfileDir' | 'virtualStoreDirMaxLength'> & {
|
||||
depth?: number
|
||||
include: IncludedDependencies
|
||||
long?: boolean
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -47,4 +47,5 @@ export const DEFAULT_OPTS = {
|
||||
useRunningStoreServer: false,
|
||||
useStoreServer: false,
|
||||
workspaceConcurrency: 4,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -51,4 +51,5 @@ export const DEFAULT_OPTS = {
|
||||
useRunningStoreServer: false,
|
||||
useStoreServer: false,
|
||||
workspaceConcurrency: 4,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)({
|
||||
|
||||
@@ -20,10 +20,11 @@ export interface StrictStoreStatusOptions {
|
||||
development: boolean
|
||||
optional: boolean
|
||||
binsDir: string
|
||||
virtualStoreDirMaxLength: number
|
||||
}
|
||||
|
||||
export type StoreStatusOptions = Partial<StrictStoreStatusOptions> &
|
||||
Pick<StrictStoreStatusOptions, 'storeDir'>
|
||||
Pick<StrictStoreStatusOptions, 'storeDir' | 'virtualStoreDirMaxLength'>
|
||||
|
||||
const defaults = async (opts: StoreStatusOptions): Promise<StrictStoreStatusOptions> => {
|
||||
const dir = opts.dir ?? process.cwd()
|
||||
|
||||
@@ -50,9 +50,9 @@ export async function storeStatus (maybeOpts: StoreStatusOptions): Promise<strin
|
||||
const modified = await pFilter(pkgs, async ({ id, integrity, depPath, name }) => {
|
||||
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<PackageFilesIndex>(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') {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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'])
|
||||
})
|
||||
|
||||
@@ -30,6 +30,7 @@ async function createStoreController (storeDir?: string) {
|
||||
cacheDir,
|
||||
storeDir,
|
||||
verifyStoreIntegrity: true,
|
||||
virtualStoreDirMaxLength: 120,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ export type CreateNewStoreControllerOptions = CreateResolverOptions & Pick<Confi
|
||||
| 'unsafePerm'
|
||||
| 'userAgent'
|
||||
| 'verifyStoreIntegrity'
|
||||
| 'virtualStoreDirMaxLength'
|
||||
> & {
|
||||
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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user