mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-10 18:18:56 -04:00
6
.changeset/quiet-brooms-serve.md
Normal file
6
.changeset/quiet-brooms-serve.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/core": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Sort keys in `packageExtensions` before calculating `packageExtensionsChecksum`. Fix [#6824](https://github.com/pnpm/pnpm/issues/6824).
|
||||
@@ -67,6 +67,7 @@
|
||||
"ramda": "npm:@pnpm/ramda@0.28.1",
|
||||
"run-groups": "^3.0.1",
|
||||
"semver": "^7.5.4",
|
||||
"sort-keys": "^4.2.0",
|
||||
"version-selector-type": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
60
pkg-manager/core/src/install/index.test.ts
Normal file
60
pkg-manager/core/src/install/index.test.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { createObjectChecksum } from './index'
|
||||
|
||||
function assets () {
|
||||
const sorted = {
|
||||
abc: {
|
||||
a: 0,
|
||||
b: [0, 1, 2],
|
||||
c: null,
|
||||
},
|
||||
def: {
|
||||
foo: 'bar',
|
||||
hello: 'world',
|
||||
},
|
||||
} as const
|
||||
|
||||
const unsorted1 = {
|
||||
abc: {
|
||||
b: [0, 1, 2],
|
||||
a: 0,
|
||||
c: null,
|
||||
},
|
||||
def: {
|
||||
hello: 'world',
|
||||
foo: 'bar',
|
||||
},
|
||||
} as const
|
||||
|
||||
const unsorted2 = {
|
||||
def: {
|
||||
foo: 'bar',
|
||||
hello: 'world',
|
||||
},
|
||||
abc: {
|
||||
a: 0,
|
||||
b: [0, 1, 2],
|
||||
c: null,
|
||||
},
|
||||
} as const
|
||||
|
||||
const unsorted3 = {
|
||||
def: {
|
||||
hello: 'world',
|
||||
foo: 'bar',
|
||||
},
|
||||
abc: {
|
||||
b: [0, 1, 2],
|
||||
a: 0,
|
||||
c: null,
|
||||
},
|
||||
} as const
|
||||
|
||||
return { sorted, unsorted1, unsorted2, unsorted3 } as const
|
||||
}
|
||||
|
||||
test('createObjectChecksum', () => {
|
||||
const { sorted, unsorted1, unsorted2, unsorted3 } = assets()
|
||||
expect(createObjectChecksum(unsorted1)).toBe(createObjectChecksum(sorted))
|
||||
expect(createObjectChecksum(unsorted2)).toBe(createObjectChecksum(sorted))
|
||||
expect(createObjectChecksum(unsorted3)).toBe(createObjectChecksum(sorted))
|
||||
})
|
||||
@@ -72,6 +72,7 @@ import pickBy from 'ramda/src/pickBy'
|
||||
import pipeWith from 'ramda/src/pipeWith'
|
||||
import props from 'ramda/src/props'
|
||||
import unnest from 'ramda/src/unnest'
|
||||
import sortKeys from 'sort-keys'
|
||||
import { parseWantedDependencies } from '../parseWantedDependencies'
|
||||
import { removeDeps } from '../uninstall/removeDeps'
|
||||
import { allProjectsAreUpToDate } from './allProjectsAreUpToDate'
|
||||
@@ -749,8 +750,8 @@ function getOutdatedLockfileSetting (
|
||||
return null
|
||||
}
|
||||
|
||||
export function createObjectChecksum (obj: unknown) {
|
||||
const s = JSON.stringify(obj)
|
||||
export function createObjectChecksum (obj: Record<string, unknown>) {
|
||||
const s = JSON.stringify(sortKeys(obj, { deep: true }))
|
||||
return crypto.createHash('md5').update(s).digest('hex')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { PnpmError } from '@pnpm/error'
|
||||
import { prepareEmpty } from '@pnpm/prepare'
|
||||
import { addDependenciesToPackage, mutateModulesInSingleProject } from '@pnpm/core'
|
||||
import { type PackageExtension } from '@pnpm/types'
|
||||
import { addDependenciesToPackage, mutateModulesInSingleProject, install } from '@pnpm/core'
|
||||
import { type PackageExtension, type ProjectManifest } from '@pnpm/types'
|
||||
import { createObjectChecksum } from '../../lib/install/index'
|
||||
import {
|
||||
testDefaults,
|
||||
@@ -94,6 +94,58 @@ test('manifests are extended with fields specified by packageExtensions', async
|
||||
)
|
||||
})
|
||||
|
||||
test('packageExtensionsChecksum does not change regardless of keys order', async () => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
const packageExtensions1: Record<string, PackageExtension> = {
|
||||
'is-odd': {
|
||||
peerDependencies: {
|
||||
'is-number': '*',
|
||||
},
|
||||
},
|
||||
'is-even': {
|
||||
peerDependencies: {
|
||||
'is-number': '*',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const packageExtensions2: Record<string, PackageExtension> = {
|
||||
'is-even': {
|
||||
peerDependencies: {
|
||||
'is-number': '*',
|
||||
},
|
||||
},
|
||||
'is-odd': {
|
||||
peerDependencies: {
|
||||
'is-number': '*',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const manifest = (): ProjectManifest => ({
|
||||
dependencies: {
|
||||
'is-even': '*',
|
||||
'is-odd': '*',
|
||||
},
|
||||
})
|
||||
|
||||
await install(manifest(), await testDefaults({
|
||||
packageExtensions: packageExtensions1,
|
||||
}))
|
||||
const lockfile1 = await project.readLockfile()
|
||||
const checksum1 = lockfile1.packageExtensionsChecksum
|
||||
|
||||
await install(manifest(), await testDefaults({
|
||||
packageExtensions: packageExtensions2,
|
||||
}))
|
||||
const lockfile2 = await project.readLockfile()
|
||||
const checksum2 = lockfile2.packageExtensionsChecksum
|
||||
|
||||
expect(checksum1).toBe(checksum2)
|
||||
expect(checksum1).not.toBeFalsy()
|
||||
})
|
||||
|
||||
test('manifests are patched by extensions from the compatibility database', async () => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
|
||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -3000,6 +3000,9 @@ importers:
|
||||
semver:
|
||||
specifier: ^7.5.4
|
||||
version: 7.5.4
|
||||
sort-keys:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0
|
||||
version-selector-type:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
|
||||
Reference in New Issue
Block a user