mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-30 20:16:38 -04:00
fix: use headless install for injected self-referencing file: dependencies (#10714)
When a package has an injected self-referencing dependency (e.g. "pkg": "file:" with dependenciesMeta injected: true), the lockfile resolves it as "link:". The linkedPackagesAreUpToDate() function incorrectly reported these projects as not up-to-date because refToRelative() returns null for link: refs, causing pnpm to skip the fast headless install path and do full resolution instead.
This commit is contained in:
6
.changeset/fix-headless-install-injected-self-ref.md
Normal file
6
.changeset/fix-headless-install-injected-self-ref.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/lockfile.verification": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Fix headless install not being used when a project has an injected self-referencing `file:` dependency that resolves to `link:` in the lockfile.
|
||||
@@ -52,6 +52,10 @@ export async function linkedPackagesAreUpToDate (
|
||||
if (!currentSpec) return true
|
||||
const lockfileRef = lockfileDeps[depName]
|
||||
if (refIsLocalDirectory(project.snapshot.specifiers[depName])) {
|
||||
// When a file: specifier resolves to link: in the lockfile
|
||||
// (e.g. injected self-references), it's a local link with no
|
||||
// entry in the packages section. Treat it as up-to-date.
|
||||
if (lockfileRef.startsWith('link:')) return true
|
||||
const depPath = refToRelative(lockfileRef, depName)
|
||||
return depPath != null && isLocalFileDepUpdated(lockfileDir, lockfilePackages?.[depPath])
|
||||
}
|
||||
|
||||
@@ -867,6 +867,52 @@ test('allProjectsAreUpToDate(): returns true if one of the importers is not pres
|
||||
})).toBeTruthy()
|
||||
})
|
||||
|
||||
test('allProjectsAreUpToDate(): returns true for injected self-referencing file: dependency resolved as link:', async () => {
|
||||
expect(await allProjectsAreUpToDate([
|
||||
{
|
||||
id: 'can-link' as ProjectId,
|
||||
manifest: {
|
||||
name: 'can-link',
|
||||
version: '2.0.0',
|
||||
dependenciesMeta: {
|
||||
'can-link': {
|
||||
injected: true,
|
||||
},
|
||||
},
|
||||
devDependencies: {
|
||||
'can-link': 'file:',
|
||||
},
|
||||
},
|
||||
rootDir: 'can-link' as ProjectRootDir,
|
||||
},
|
||||
], {
|
||||
autoInstallPeers: false,
|
||||
catalogs: {},
|
||||
excludeLinksFromLockfile: false,
|
||||
linkWorkspacePackages: false,
|
||||
wantedLockfile: {
|
||||
importers: {
|
||||
['can-link' as ProjectId]: {
|
||||
dependenciesMeta: {
|
||||
'can-link': {
|
||||
injected: true,
|
||||
},
|
||||
},
|
||||
devDependencies: {
|
||||
'can-link': 'link:',
|
||||
},
|
||||
specifiers: {
|
||||
'can-link': 'file:',
|
||||
},
|
||||
},
|
||||
},
|
||||
lockfileVersion: LOCKFILE_VERSION,
|
||||
},
|
||||
workspacePackages: new Map(),
|
||||
lockfileDir: '',
|
||||
})).toBeTruthy()
|
||||
})
|
||||
|
||||
test('allProjectsAreUpToDate(): returns false if the lockfile is broken, the resolved versions do not satisfy the ranges', async () => {
|
||||
expect(await allProjectsAreUpToDate([
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user