feat!: use SHA256 for hashing the pnpmfile content (#8530)

This commit is contained in:
Zoltan Kochan
2024-09-16 01:19:03 +02:00
committed by GitHub
parent dcd2917ec7
commit bcffd4d72b
9 changed files with 36 additions and 11 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/pnpmfile": major
"pnpm": major
---
Use SHA256 for storing the pnpmfile checksum in the lockfile [#8530](https://github.com/pnpm/pnpm/pull/8530).

View File

@@ -1,7 +1,19 @@
import crypto from 'crypto' import crypto from 'crypto'
import fs from 'fs'
export function createShortHash (input: string): string { export function createShortHash (input: string): string {
const hash = crypto.createHash('sha256') const hash = crypto.createHash('sha256')
hash.update(input) hash.update(input)
return hash.digest('hex').substring(0, 32) return hash.digest('hex').substring(0, 32)
} }
export function createHash (input: string): string {
const hash = crypto.createHash('sha256')
hash.update(input)
return `sha256-${hash.digest('base64')}`
}
export async function createHashFromFile (file: string): Promise<string> {
const content = await fs.promises.readFile(file, 'utf8')
return createHash(content.split('\r\n').join('\n'))
}

View File

@@ -35,7 +35,7 @@
}, },
"dependencies": { "dependencies": {
"@pnpm/core-loggers": "workspace:*", "@pnpm/core-loggers": "workspace:*",
"@pnpm/crypto.base32-hash": "workspace:*", "@pnpm/crypto.hash": "workspace:*",
"@pnpm/error": "workspace:*", "@pnpm/error": "workspace:*",
"@pnpm/hooks.types": "workspace:*", "@pnpm/hooks.types": "workspace:*",
"@pnpm/lockfile.types": "workspace:*", "@pnpm/lockfile.types": "workspace:*",

View File

@@ -1,6 +1,6 @@
import type { PreResolutionHookContext, PreResolutionHookLogger } from '@pnpm/hooks.types' import type { PreResolutionHookContext, PreResolutionHookLogger } from '@pnpm/hooks.types'
import { hookLogger } from '@pnpm/core-loggers' import { hookLogger } from '@pnpm/core-loggers'
import { createBase32HashFromFile } from '@pnpm/crypto.base32-hash' import { createHashFromFile } from '@pnpm/crypto.hash'
import pathAbsolute from 'path-absolute' import pathAbsolute from 'path-absolute'
import type { CustomFetchers } from '@pnpm/fetcher-base' import type { CustomFetchers } from '@pnpm/fetcher-base'
import { type ImportIndexedPackageAsync } from '@pnpm/store-controller-types' import { type ImportIndexedPackageAsync } from '@pnpm/store-controller-types'
@@ -40,7 +40,7 @@ export function requireHooks (
let hooks: Hooks | undefined = pnpmFile?.hooks let hooks: Hooks | undefined = pnpmFile?.hooks
if (!globalHooks && !hooks) return { afterAllResolved: [], filterLog: [], readPackage: [] } if (!globalHooks && !hooks) return { afterAllResolved: [], filterLog: [], readPackage: [] }
const calculatePnpmfileChecksum = hooks ? () => createBase32HashFromFile(pnpmfilePath) : undefined const calculatePnpmfileChecksum = hooks ? () => createHashFromFile(pnpmfilePath) : undefined
globalHooks = globalHooks ?? {} globalHooks = globalHooks ?? {}
hooks = hooks ?? {} hooks = hooks ?? {}
const cookedHooks: CookedHooks & Required<Pick<CookedHooks, 'filterLog'>> = { const cookedHooks: CookedHooks & Required<Pick<CookedHooks, 'filterLog'>> = {

View File

@@ -9,6 +9,9 @@
"../../__typings__/**/*.d.ts" "../../__typings__/**/*.d.ts"
], ],
"references": [ "references": [
{
"path": "../../crypto/hash"
},
{ {
"path": "../../fetching/fetcher-base" "path": "../../fetching/fetcher-base"
}, },
@@ -18,9 +21,6 @@
{ {
"path": "../../packages/core-loggers" "path": "../../packages/core-loggers"
}, },
{
"path": "../../packages/crypto.base32-hash"
},
{ {
"path": "../../packages/error" "path": "../../packages/error"
}, },

7
pnpm-lock.yaml generated
View File

@@ -2667,9 +2667,9 @@ importers:
'@pnpm/core-loggers': '@pnpm/core-loggers':
specifier: workspace:* specifier: workspace:*
version: link:../../packages/core-loggers version: link:../../packages/core-loggers
'@pnpm/crypto.base32-hash': '@pnpm/crypto.hash':
specifier: workspace:* specifier: workspace:*
version: link:../../packages/crypto.base32-hash version: link:../../crypto/hash
'@pnpm/error': '@pnpm/error':
specifier: workspace:* specifier: workspace:*
version: link:../../packages/error version: link:../../packages/error
@@ -5494,6 +5494,9 @@ importers:
'@pnpm/crypto.base32-hash': '@pnpm/crypto.base32-hash':
specifier: workspace:* specifier: workspace:*
version: link:../packages/crypto.base32-hash version: link:../packages/crypto.base32-hash
'@pnpm/crypto.hash':
specifier: workspace:*
version: link:../crypto/hash
'@pnpm/default-reporter': '@pnpm/default-reporter':
specifier: workspace:* specifier: workspace:*
version: link:../cli/default-reporter version: link:../cli/default-reporter

View File

@@ -32,6 +32,7 @@
"@pnpm/config": "workspace:*", "@pnpm/config": "workspace:*",
"@pnpm/constants": "workspace:*", "@pnpm/constants": "workspace:*",
"@pnpm/core-loggers": "workspace:*", "@pnpm/core-loggers": "workspace:*",
"@pnpm/crypto.hash": "workspace:*",
"@pnpm/crypto.base32-hash": "workspace:*", "@pnpm/crypto.base32-hash": "workspace:*",
"@pnpm/default-reporter": "workspace:*", "@pnpm/default-reporter": "workspace:*",
"@pnpm/dependency-path": "workspace:*", "@pnpm/dependency-path": "workspace:*",

View File

@@ -1,6 +1,6 @@
import fs from 'fs' import fs from 'fs'
import path from 'path' import path from 'path'
import { createBase32Hash } from '@pnpm/crypto.base32-hash' import { createHash } from '@pnpm/crypto.hash'
import { type PackageManifest } from '@pnpm/types' import { type PackageManifest } from '@pnpm/types'
import { prepare, preparePackages } from '@pnpm/prepare' import { prepare, preparePackages } from '@pnpm/prepare'
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock' import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
@@ -253,7 +253,7 @@ test('adding or changing pnpmfile should change pnpmfileChecksum and module stru
await execPnpm(['install']) await execPnpm(['install'])
const lockfile1 = project.readLockfile() const lockfile1 = project.readLockfile()
expect(lockfile1.pnpmfileChecksum).toBe(createBase32Hash(pnpmfile1)) expect(lockfile1.pnpmfileChecksum).toBe(createHash(pnpmfile1))
expect(lockfile1.packages).toHaveProperty(['@pnpm.e2e/pkg-with-good-optional@1.0.0']) expect(lockfile1.packages).toHaveProperty(['@pnpm.e2e/pkg-with-good-optional@1.0.0'])
expect(lockfile1.packages).not.toHaveProperty(['is-positive@1.0.0']) // this should be removed due to being optional dependency expect(lockfile1.packages).not.toHaveProperty(['is-positive@1.0.0']) // this should be removed due to being optional dependency
@@ -274,7 +274,7 @@ test('adding or changing pnpmfile should change pnpmfileChecksum and module stru
await execPnpm(['install']) await execPnpm(['install'])
const lockfile2 = project.readLockfile() const lockfile2 = project.readLockfile()
expect(lockfile2.pnpmfileChecksum).toBe(createBase32Hash(pnpmfile2)) expect(lockfile2.pnpmfileChecksum).toBe(createHash(pnpmfile2))
expect(lockfile2.snapshots).toMatchObject({ expect(lockfile2.snapshots).toMatchObject({
'@pnpm.e2e/foo@100.0.0': expect.any(Object), '@pnpm.e2e/foo@100.0.0': expect.any(Object),
'@pnpm.e2e/bar@100.0.0': expect.any(Object), '@pnpm.e2e/bar@100.0.0': expect.any(Object),

View File

@@ -54,6 +54,9 @@
{ {
"path": "../config/plugin-commands-config" "path": "../config/plugin-commands-config"
}, },
{
"path": "../crypto/hash"
},
{ {
"path": "../env/path" "path": "../env/path"
}, },