feat!: use sha256 for hashing long paths inside node_modules/.pnpm

This commit is contained in:
Zoltan Kochan
2024-09-15 18:28:55 +02:00
parent d433cb9c9f
commit dcd2917ec7
17 changed files with 137 additions and 10 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/dependency-path": major
"pnpm": major
---
Use sha256 for hashing long paths inside `node_modules/.pnpm`.

View File

@@ -0,0 +1,5 @@
---
"pnpm": major
---
Using SHA256 instead of md5 for hashing long peer dependency hashes in the lockfile. Should not affect a lot of users as the hashing is used for really long keys in the lockfile.

View File

@@ -0,0 +1,5 @@
---
"@pnpm/crypto.hash": major
---
Initial release.

13
crypto/hash/README.md Normal file
View File

@@ -0,0 +1,13 @@
# @pnpm/crypto.hash
> Generate hashes
## Installation
```sh
pnpm add @pnpm/crypto.hash
```
## License
MIT

View File

@@ -0,0 +1,3 @@
const config = require('../../jest.config.js');
module.exports = Object.assign({}, config, {});

39
crypto/hash/package.json Normal file
View File

@@ -0,0 +1,39 @@
{
"name": "@pnpm/crypto.hash",
"version": "0.0.0",
"description": "Generate hashes",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib",
"!*.map"
],
"scripts": {
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
"_test": "jest",
"test": "pnpm run compile && pnpm run _test",
"prepublishOnly": "pnpm run compile",
"compile": "tsc --build && pnpm run lint --fix"
},
"repository": "https://github.com/pnpm/pnpm/blob/main/crypto/hash",
"keywords": [
"pnpm9",
"hash",
"crypto"
],
"engines": {
"node": ">=18.12"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/pnpm/pnpm/issues"
},
"homepage": "https://github.com/pnpm/pnpm/blob/main/crypto/hash#readme",
"devDependencies": {
"@pnpm/crypto.hash": "workspace:*"
},
"funding": "https://opencollective.com/pnpm",
"exports": {
".": "./lib/index.js"
}
}

7
crypto/hash/src/index.ts Normal file
View File

@@ -0,0 +1,7 @@
import crypto from 'crypto'
export function createShortHash (input: string): string {
const hash = crypto.createHash('sha256')
hash.update(input)
return hash.digest('hex').substring(0, 32)
}

View File

@@ -0,0 +1,6 @@
/// <reference path="../../../__typings__/index.d.ts"/>
import { createShortHash } from '@pnpm/crypto.hash'
test('createShortHash()', () => {
expect(createShortHash('AAA')).toEqual('cb1ad2119d8fafb69566510ee712661f')
})

View File

@@ -0,0 +1,17 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"noEmit": false,
"outDir": "../test.lib",
"rootDir": "."
},
"include": [
"**/*.ts",
"../../../__typings__/**/*.d.ts"
],
"references": [
{
"path": ".."
}
]
}

12
crypto/hash/tsconfig.json Normal file
View File

@@ -0,0 +1,12 @@
{
"extends": "@pnpm/tsconfig",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src"
},
"include": [
"src/**/*.ts",
"../../__typings__/**/*.d.ts"
],
"references": []
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"include": [
"src/**/*.ts",
"test/**/*.ts",
"../../__typings__/**/*.d.ts"
]
}

View File

@@ -31,7 +31,7 @@
},
"homepage": "https://github.com/pnpm/pnpm/blob/main/packages/dependency-path#readme",
"dependencies": {
"@pnpm/crypto.base32-hash": "workspace:*",
"@pnpm/crypto.hash": "workspace:*",
"@pnpm/types": "workspace:*",
"semver": "catalog:"
},

View File

@@ -1,4 +1,4 @@
import { createBase32Hash } from '@pnpm/crypto.base32-hash'
import { createShortHash } from '@pnpm/crypto.hash'
import { type DepPath, type PkgResolutionId, type Registries, type PkgId, type PkgIdWithPatchHash } from '@pnpm/types'
import semver from 'semver'
@@ -172,7 +172,7 @@ export function depPathToFilename (depPath: string, maxLengthWithoutHash: number
.replace(/(\)\()|\(|\)/g, '_')
}
if (filename.length > maxLengthWithoutHash || filename !== filename.toLowerCase() && !filename.startsWith('file+')) {
return `${filename.substring(0, maxLengthWithoutHash - 27)}_${createBase32Hash(filename)}`
return `${filename.substring(0, maxLengthWithoutHash - 33)}_${createShortHash(filename)}`
}
return filename
}
@@ -204,7 +204,7 @@ export function createPeersDirSuffix (peerIds: PeerId[], maxLength: number = 100
}
).sort().join(')(')
if (dirName.length > maxLength) {
dirName = createBase32Hash(dirName)
dirName = createShortHash(dirName)
}
return `(${dirName})`
}

View File

@@ -96,8 +96,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), 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
expect(depPathToFilename('abcd/'.repeat(200), 120)).toBe('abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+ab_e7c10c3598ebbc0ca640b6524c68e602') // cspell:disable-line
expect(depPathToFilename('/JSONSteam@1.0.0', 120)).toBe('JSONSteam@1.0.0_533d3b11e9111b7a24f914844c021ddf') // cspell:disable-line
})
test('tryGetPackageId', () => {

View File

@@ -10,7 +10,7 @@
],
"references": [
{
"path": "../crypto.base32-hash"
"path": "../../crypto/hash"
},
{
"path": "../types"

View File

@@ -1574,5 +1574,5 @@ test('setting a custom peersSuffixMaxLength', async () => {
const lockfile = project.readLockfile()
expect(lockfile.settings.peersSuffixMaxLength).toBe(10)
expect(lockfile.importers['.']?.dependencies?.['@pnpm.e2e/abc']?.version?.length).toBe(33)
expect(lockfile.importers['.']?.dependencies?.['@pnpm.e2e/abc']?.version?.length).toBe(39)
})

10
pnpm-lock.yaml generated
View File

@@ -1554,6 +1554,12 @@ importers:
specifier: 'catalog:'
version: 1.3.31
crypto/hash:
devDependencies:
'@pnpm/crypto.hash':
specifier: workspace:*
version: 'link:'
crypto/object-hasher:
dependencies:
object-hash:
@@ -3468,9 +3474,9 @@ importers:
packages/dependency-path:
dependencies:
'@pnpm/crypto.base32-hash':
'@pnpm/crypto.hash':
specifier: workspace:*
version: link:../crypto.base32-hash
version: link:../../crypto/hash
'@pnpm/types':
specifier: workspace:*
version: link:../types