mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-23 23:29:17 -05:00
fix!: always create a lockfile (#6073)
This commit is contained in:
6
.changeset/witty-paws-heal.md
Normal file
6
.changeset/witty-paws-heal.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/lockfile-file": major
|
||||
"pnpm": major
|
||||
---
|
||||
|
||||
Create a lockfile even if the project has no dependencies at all.
|
||||
1
__fixtures__/empty/pnpm-lock.yaml
generated
Normal file
1
__fixtures__/empty/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1 @@
|
||||
lockfileVersion: '6.0'
|
||||
1
__fixtures__/local-pkg/pnpm-lock.yaml
generated
Normal file
1
__fixtures__/local-pkg/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1 @@
|
||||
lockfileVersion: '6.0'
|
||||
1
__fixtures__/local-scoped-pkg/pnpm-lock.yaml
generated
Normal file
1
__fixtures__/local-scoped-pkg/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1 @@
|
||||
lockfileVersion: '6.0'
|
||||
1
__fixtures__/pnpm-lock.yaml
generated
Normal file
1
__fixtures__/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1 @@
|
||||
lockfileVersion: '6.0'
|
||||
1
__fixtures__/tar-pkg/pnpm-lock.yaml
generated
Normal file
1
__fixtures__/tar-pkg/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1 @@
|
||||
lockfileVersion: '6.0'
|
||||
1
__fixtures__/workspace-has-shared-npm-shrinkwrap-json/pnpm-lock.yaml
generated
Normal file
1
__fixtures__/workspace-has-shared-npm-shrinkwrap-json/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1 @@
|
||||
lockfileVersion: '6.0'
|
||||
1
__fixtures__/workspace-has-shared-package-lock-json/pnpm-lock.yaml
generated
Normal file
1
__fixtures__/workspace-has-shared-package-lock-json/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1 @@
|
||||
lockfileVersion: '6.0'
|
||||
1
__fixtures__/workspace-has-shared-yarn-lock/pnpm-lock.yaml
generated
Normal file
1
__fixtures__/workspace-has-shared-yarn-lock/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1 @@
|
||||
lockfileVersion: '6.0'
|
||||
@@ -1,4 +1,5 @@
|
||||
export {
|
||||
isEmptyLockfile,
|
||||
writeLockfiles,
|
||||
writeCurrentLockfile,
|
||||
writeWantedLockfile,
|
||||
|
||||
@@ -53,6 +53,11 @@ export async function writeCurrentLockfile (
|
||||
forceSharedFormat?: boolean
|
||||
}
|
||||
) {
|
||||
// empty lockfile is not saved
|
||||
if (isEmptyLockfile(currentLockfile)) {
|
||||
await rimraf(path.join(virtualStoreDir, 'lock.yaml'))
|
||||
return
|
||||
}
|
||||
await fs.mkdir(virtualStoreDir, { recursive: true })
|
||||
return writeLockfile('lock.yaml', virtualStoreDir, currentLockfile, opts)
|
||||
}
|
||||
@@ -70,11 +75,6 @@ async function writeLockfile (
|
||||
) {
|
||||
const lockfilePath = path.join(pkgPath, lockfileFilename)
|
||||
|
||||
// empty lockfile is not saved
|
||||
if (isEmptyLockfile(wantedLockfile)) {
|
||||
return rimraf(lockfilePath)
|
||||
}
|
||||
|
||||
const isLockfileV6 = wantedLockfile['lockfileVersion'].toString().startsWith('6.')
|
||||
const lockfileToStringify = (Boolean(opts?.useInlineSpecifiersFormat) || isLockfileV6)
|
||||
? convertToInlineSpecifiersFormat(wantedLockfile) as unknown as Lockfile
|
||||
@@ -94,7 +94,7 @@ function yamlStringify (lockfile: Lockfile, opts: NormalizeLockfileOpts) {
|
||||
return yaml.dump(normalizedLockfile, LOCKFILE_YAML_FORMAT)
|
||||
}
|
||||
|
||||
function isEmptyLockfile (lockfile: Lockfile) {
|
||||
export function isEmptyLockfile (lockfile: Lockfile) {
|
||||
return Object.values(lockfile.importers).every((importer) => isEmpty(importer.specifiers ?? {}) && isEmpty(importer.dependencies ?? {}))
|
||||
}
|
||||
|
||||
@@ -240,15 +240,6 @@ export async function writeLockfiles (
|
||||
const wantedLockfilePath = path.join(opts.wantedLockfileDir, wantedLockfileName)
|
||||
const currentLockfilePath = path.join(opts.currentLockfileDir, 'lock.yaml')
|
||||
|
||||
// empty lockfile is not saved
|
||||
if (isEmptyLockfile(opts.wantedLockfile)) {
|
||||
await Promise.all([
|
||||
rimraf(wantedLockfilePath),
|
||||
rimraf(currentLockfilePath),
|
||||
])
|
||||
return
|
||||
}
|
||||
|
||||
const forceSharedFormat = opts?.forceSharedFormat === true
|
||||
const isLockfileV6 = opts.wantedLockfile.lockfileVersion.toString().startsWith('6.')
|
||||
const wantedLockfileToStringify = (Boolean(opts.useInlineSpecifiersFormat) || isLockfileV6)
|
||||
@@ -267,8 +258,12 @@ export async function writeLockfiles (
|
||||
await Promise.all([
|
||||
writeFileAtomic(wantedLockfilePath, yamlDoc),
|
||||
(async () => {
|
||||
await fs.mkdir(path.dirname(currentLockfilePath), { recursive: true })
|
||||
await writeFileAtomic(currentLockfilePath, yamlDoc)
|
||||
if (isEmptyLockfile(opts.wantedLockfile)) {
|
||||
await rimraf(currentLockfilePath)
|
||||
} else {
|
||||
await fs.mkdir(path.dirname(currentLockfilePath), { recursive: true })
|
||||
await writeFileAtomic(currentLockfilePath, yamlDoc)
|
||||
}
|
||||
})(),
|
||||
])
|
||||
return
|
||||
@@ -287,8 +282,12 @@ export async function writeLockfiles (
|
||||
await Promise.all([
|
||||
writeFileAtomic(wantedLockfilePath, yamlDoc),
|
||||
(async () => {
|
||||
await fs.mkdir(path.dirname(currentLockfilePath), { recursive: true })
|
||||
await writeFileAtomic(currentLockfilePath, currentYamlDoc)
|
||||
if (isEmptyLockfile(opts.wantedLockfile)) {
|
||||
await rimraf(currentLockfilePath)
|
||||
} else {
|
||||
await fs.mkdir(path.dirname(currentLockfilePath), { recursive: true })
|
||||
await writeFileAtomic(currentLockfilePath, currentYamlDoc)
|
||||
}
|
||||
})(),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -141,16 +141,16 @@ test("lockfile doesn't lock subdependencies that don't satisfy the new specs", a
|
||||
expect(Object.keys(lockfile.dependencies).length).toBe(1) // resolutions not duplicated
|
||||
})
|
||||
|
||||
test('lockfile not created when no deps in package.json', async () => {
|
||||
test('a lockfile created even when there are no deps in package.json', async () => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
await install({}, await testDefaults())
|
||||
|
||||
expect(await project.readLockfile()).toBeFalsy()
|
||||
expect(await project.readLockfile()).toBeTruthy()
|
||||
expect(await exists('node_modules')).toBeFalsy()
|
||||
})
|
||||
|
||||
test('lockfile removed when no deps in package.json', async () => {
|
||||
test('current lockfile removed when no deps in package.json', async () => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
await writeYamlFile(WANTED_LOCKFILE, {
|
||||
@@ -172,7 +172,8 @@ test('lockfile removed when no deps in package.json', async () => {
|
||||
|
||||
await install({}, await testDefaults())
|
||||
|
||||
expect(await project.readLockfile()).toBeFalsy()
|
||||
expect(await project.readLockfile()).toBeTruthy()
|
||||
expect(await exists('node_modules')).toBeFalsy()
|
||||
})
|
||||
|
||||
test('lockfile is fixed when it does not match package.json', async () => {
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
import {
|
||||
createLockfileObject,
|
||||
existsWantedLockfile,
|
||||
isEmptyLockfile,
|
||||
Lockfile,
|
||||
readCurrentLockfile,
|
||||
readWantedLockfile,
|
||||
@@ -126,7 +127,7 @@ export async function readLockfiles (
|
||||
currentLockfile,
|
||||
currentLockfileIsUpToDate: equals(currentLockfile, wantedLockfile),
|
||||
existsCurrentLockfile: files[1] != null,
|
||||
existsWantedLockfile: files[0] != null,
|
||||
existsWantedLockfile: files[0] != null && !isEmptyLockfile(wantedLockfile),
|
||||
wantedLockfile,
|
||||
lockfileHadConflicts,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user