feat: use a shorter hash for dep path (#4552)

This commit is contained in:
Zoltan Kochan
2022-04-13 12:05:07 +03:00
committed by GitHub
parent 5e79891033
commit 0a70aedb1c
10 changed files with 50 additions and 26 deletions

View File

@@ -0,0 +1,5 @@
---
"dependency-path": minor
---
Export new function: createPeersFolderSuffix().

View File

@@ -0,0 +1,7 @@
---
"@pnpm/core": major
"@pnpm/resolve-dependencies": major
"pnpm": major
---
Use a base32 hash instead of a hex to encode too long dependency paths.

View File

@@ -1164,7 +1164,7 @@ test('resolve a subdependency from the workspace and use it as a peer', async ()
'/abc-grand-parent-with-c/1.0.0',
'/abc-parent-with-ab/1.0.0',
'/abc-parent-with-ab/1.0.0_peer-c@1.0.1',
'/abc/1.0.0_2ff3f699e79762943311edf90e6e1302',
'/abc/1.0.0_f7z7ngphs5rjimyr5x4q43qtai',
'/abc/1.0.0_peer-a@peer-a+peer-b@1.0.0',
'/dep-of-pkg-with-1-dep/100.0.0',
'/is-positive/1.0.0',

View File

@@ -438,14 +438,14 @@ test('peer dependencies are linked when running one named installation', async (
const pkgVariationsDir = path.resolve('node_modules/.pnpm/abc@1.0.0')
const pkgVariation1 = path.join(pkgVariationsDir + '_165e1e08a3f7e7f77ddb572ad0e55660/node_modules')
const pkgVariation1 = path.join(pkgVariationsDir + '_6ea473aweg4rki46lsbci3nehq/node_modules')
await okFile(path.join(pkgVariation1, 'abc'))
await okFile(path.join(pkgVariation1, 'peer-a'))
await okFile(path.join(pkgVariation1, 'peer-b'))
await okFile(path.join(pkgVariation1, 'peer-c'))
await okFile(path.join(pkgVariation1, 'dep-of-pkg-with-1-dep'))
const pkgVariation2 = path.join(pkgVariationsDir + '_f101cfec1621b915239e5c82246da43c/node_modules')
const pkgVariation2 = path.join(pkgVariationsDir + '_czpb4cfd67t7o7o3k4vnbzkwma/node_modules')
await okFile(path.join(pkgVariation2, 'abc'))
await okFile(path.join(pkgVariation2, 'peer-a'))
await okFile(path.join(pkgVariation2, 'peer-b'))
@@ -461,6 +461,7 @@ test('peer dependencies are linked when running one named installation', async (
})
test('peer dependencies are linked when running two separate named installations', async () => {
await addDistTag({ package: 'abc-parent-with-ab', version: '1.0.0', distTag: 'latest' })
await addDistTag({ package: 'peer-a', version: '1.0.0', distTag: 'latest' })
await addDistTag({ package: 'peer-c', version: '1.0.0', distTag: 'latest' })
prepareEmpty()
@@ -470,14 +471,14 @@ test('peer dependencies are linked when running two separate named installations
const pkgVariationsDir = path.resolve('node_modules/.pnpm/abc@1.0.0')
const pkgVariation1 = path.join(pkgVariationsDir + '_165e1e08a3f7e7f77ddb572ad0e55660/node_modules')
const pkgVariation1 = path.join(pkgVariationsDir + '_6ea473aweg4rki46lsbci3nehq/node_modules')
await okFile(path.join(pkgVariation1, 'abc'))
await okFile(path.join(pkgVariation1, 'peer-a'))
await okFile(path.join(pkgVariation1, 'peer-b'))
await okFile(path.join(pkgVariation1, 'peer-c'))
await okFile(path.join(pkgVariation1, 'dep-of-pkg-with-1-dep'))
const pkgVariation2 = path.join(pkgVariationsDir + '_165e1e08a3f7e7f77ddb572ad0e55660/node_modules')
const pkgVariation2 = path.join(pkgVariationsDir + '_6ea473aweg4rki46lsbci3nehq/node_modules')
await okFile(path.join(pkgVariation2, 'abc'))
await okFile(path.join(pkgVariation2, 'peer-a'))
await okFile(path.join(pkgVariation2, 'peer-b'))

View File

@@ -33,6 +33,7 @@
"dependencies": {
"@pnpm/types": "workspace:8.0.0",
"encode-registry": "^3.0.0",
"rfc4648": "^1.5.1",
"semver": "^7.3.4"
},
"devDependencies": {

View File

@@ -1,6 +1,7 @@
import crypto from 'crypto'
import { Registries } from '@pnpm/types'
import encodeRegistry from 'encode-registry'
import { base32 } from 'rfc4648'
import semver from 'semver'
export function isAbsolute (dependencyPath: string) {
@@ -132,7 +133,7 @@ export function parse (dependencyPath: string) {
export function depPathToFilename (depPath: string) {
const filename = depPathToFilenameUnescaped(depPath).replace(/\//g, '+')
if (filename.length > 120 || filename !== filename.toLowerCase() && !filename.startsWith('file+')) {
return `${filename.substring(0, 50)}_${crypto.createHash('md5').update(filename).digest('hex')}`
return `${filename.substring(0, 50)}_${createBase32Hash(filename)}`
}
return filename
}
@@ -147,3 +148,22 @@ function depPathToFilenameUnescaped (depPath: string) {
}
return depPath.replace(':', '+')
}
export function createPeersFolderSuffix (peers: Array<{name: string, version: string}>): string {
const folderName = peers.map(({ name, version }) => `${name.replace('/', '+')}@${version}`).sort().join('+')
// We don't want the folder name to get too long.
// Otherwise, an ENAMETOOLONG error might happen.
// see: https://github.com/pnpm/pnpm/issues/977
//
// A bigger limit might be fine but the base32 encoded md5 hash will be 26 symbols,
// so for consistency's sake, we go with 26.
if (folderName.length > 26) {
return `_${createBase32Hash(folderName)}`
}
return `_${folderName}`
}
function createBase32Hash (str: string): string {
return base32.stringify(crypto.createHash('md5').update(str).digest()).replace(/(=+)$/, '').toLowerCase()
}

View File

@@ -136,8 +136,8 @@ test('depPathToFilename()', () => {
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+_27524303f1ddd808db67f175ff83606e')
expect(depPathToFilename('/JSONSteam/1.0.0')).toBe('JSONSteam@1.0.0_4b2567ab922fbdf01171f59fab8f6fef')
expect(depPathToFilename('abcd/'.repeat(200))).toBe('abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+_e5jega7r3xmarw3h6f277a3any')
expect(depPathToFilename('/JSONSteam/1.0.0')).toBe('JSONSteam@1.0.0_jmswpk4sf667aelr6wp2xd3p54')
})
test('tryGetPackageId', () => {

View File

@@ -612,5 +612,5 @@ test('readPackage hook is used during removal inside a workspace', async () => {
process.chdir('..')
const lockfile = await readYamlFile<Lockfile>('pnpm-lock.yaml')
expect(lockfile.packages!['/abc/1.0.0_is-negative@1.0.0+peer-a@1.0.0'].peerDependencies!['is-negative']).toBe('1.0.0')
expect(lockfile.packages!['/abc/1.0.0_vt2fli7reel7pfbmpdhs3d7fya'].peerDependencies!['is-negative']).toBe('1.0.0')
})

View File

@@ -1,4 +1,3 @@
import crypto from 'crypto'
import filenamify from 'filenamify'
import path from 'path'
import { satisfiesWithPrereleases } from '@yarnpkg/core/lib/semverUtils'
@@ -7,7 +6,7 @@ import {
PeerDependencyIssues,
PeerDependencyIssuesByProjects,
} from '@pnpm/types'
import { depPathToFilename } from 'dependency-path'
import { depPathToFilename, createPeersFolderSuffix } from 'dependency-path'
import { KeyValuePair } from 'ramda'
import fromPairs from 'ramda/src/fromPairs'
import isEmpty from 'ramda/src/isEmpty'
@@ -511,18 +510,3 @@ function toPkgByName<T extends PartialResolvedPackage> (nodes: Array<{alias: str
}
return pkgsByName
}
function createPeersFolderSuffix (peers: Array<{name: string, version: string}>) {
const folderName = peers.map(({ name, version }) => `${name.replace('/', '+')}@${version}`).sort().join('+')
// We don't want the folder name to get too long.
// Otherwise, an ENAMETOOLONG error might happen.
// see: https://github.com/pnpm/pnpm/issues/977
//
// A bigger limit might be fine but the md5 hash will be 32 symbols,
// so for consistency's sake, we go with 32.
if (folderName.length > 32) {
return `_${crypto.createHash('md5').update(folderName).digest('hex')}`
}
return `_${folderName}`
}

6
pnpm-lock.yaml generated
View File

@@ -684,10 +684,12 @@ importers:
'@types/semver': ^7.3.4
dependency-path: workspace:9.0.0
encode-registry: ^3.0.0
rfc4648: ^1.5.1
semver: ^7.3.4
dependencies:
'@pnpm/types': link:../types
encode-registry: 3.0.0
rfc4648: 1.5.1
semver: 7.3.6
devDependencies:
'@types/semver': 7.3.9
@@ -13203,6 +13205,10 @@ packages:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
/rfc4648/1.5.1:
resolution: {integrity: sha512-60e/YWs2/D3MV1ErdjhJHcmlgnyLUiG4X/14dgsfm9/zmCWLN16xI6YqJYSCd/OANM7bUNzJqPY5B8/02S9Ibw==}
dev: false
/right-pad/1.0.1:
resolution: {integrity: sha1-jKCMLLtbVedNr6lr9/0aJ9VoyNA=}
engines: {node: '>= 0.10'}