mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 23:58:07 -05:00
fix: --lockfile-only flag causes pnpm update to ignore matchers (#9588)
* test: add regression test for `pnpm update --lockfile-only` * fix: --lockfile-only flag causes pnpm update to ignore matchers
This commit is contained in:
committed by
Zoltan Kochan
parent
3387aa95e0
commit
509948d3ae
9
.changeset/metal-frogs-cross.md
Normal file
9
.changeset/metal-frogs-cross.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
"@pnpm/resolve-dependencies": patch
|
||||
"@pnpm/package-requester": patch
|
||||
"@pnpm/store-controller-types": patch
|
||||
"@pnpm/core": patch
|
||||
pnpm: patch
|
||||
---
|
||||
|
||||
Fix a regression (in v10.9.0) causing the `--lockfile-only` flag on `pnpm update` to produce a different `pnpm-lock.yaml` than an update without the flag.
|
||||
@@ -211,6 +211,42 @@ test('update only the specified package', async () => {
|
||||
})
|
||||
})
|
||||
|
||||
test.each([false, true])('update only the specified package with --lockfile-only=%p', async (lockfileOnly) => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
await Promise.all([
|
||||
addDistTag({ package: '@pnpm.e2e/bar', version: '100.0.0', distTag: 'latest' }),
|
||||
addDistTag({ package: '@pnpm.e2e/foo', version: '100.0.0', distTag: 'latest' }),
|
||||
])
|
||||
|
||||
const { updatedManifest: manifest } = await addDependenciesToPackage({}, [
|
||||
'@pnpm.e2e/bar',
|
||||
'@pnpm.e2e/foo',
|
||||
// Ensure aliases also stay on the same version.
|
||||
'bar-alias@npm:@pnpm.e2e/bar',
|
||||
], testDefaults())
|
||||
|
||||
await Promise.all([
|
||||
addDistTag({ package: '@pnpm.e2e/bar', version: '100.1.0', distTag: 'latest' }),
|
||||
addDistTag({ package: '@pnpm.e2e/foo', version: '100.1.0', distTag: 'latest' }),
|
||||
])
|
||||
|
||||
await install(manifest, testDefaults({
|
||||
depth: Infinity,
|
||||
update: true,
|
||||
updateMatching: (pkgName: string) => pkgName === '@pnpm.e2e/foo',
|
||||
|
||||
// This test specifically tests this flag.
|
||||
lockfileOnly,
|
||||
}))
|
||||
|
||||
const lockfile = project.readLockfile()
|
||||
expect(lockfile.snapshots).toStrictEqual({
|
||||
'@pnpm.e2e/bar@100.0.0': expect.anything(),
|
||||
'@pnpm.e2e/foo@100.1.0': expect.anything(),
|
||||
})
|
||||
})
|
||||
|
||||
test('peer dependency is not added to prod deps on update', async () => {
|
||||
prepareEmpty()
|
||||
const { updatedManifest: manifest } = await install({
|
||||
|
||||
@@ -22,6 +22,7 @@ import { packageIsInstallable } from '@pnpm/package-is-installable'
|
||||
import { readPackageJson } from '@pnpm/read-package-json'
|
||||
import {
|
||||
type DirectoryResolution,
|
||||
type PreferredVersions,
|
||||
type Resolution,
|
||||
type ResolveFunction,
|
||||
type ResolveResult,
|
||||
@@ -178,13 +179,30 @@ async function resolveAndFetch (
|
||||
//
|
||||
// The resolution step is never skipped for local dependencies.
|
||||
if (!skipResolution || options.skipFetch === true || Boolean(pkgId?.startsWith('file:')) || wantedDependency.optional === true) {
|
||||
// When skipResolution is set but a resolution is still performed due to
|
||||
// options.skipFetch, it's necessary to make sure the resolution doesn't
|
||||
// accidentally return a newer version of the package. When skipFetch is
|
||||
// set, the resolved package shouldn't be different. This is done by
|
||||
// overriding the preferredVersions object to only contain the current
|
||||
// package's version.
|
||||
//
|
||||
// A naive approach would be to change the bare specifier to be the exact
|
||||
// version of the current pkg if the bare specifier is a range, but this
|
||||
// would cause the version returned for calcSpecifier to be different.
|
||||
const preferredVersions: PreferredVersions = (skipResolution && options.currentPkg?.name != null && options.currentPkg?.version != null)
|
||||
? {
|
||||
...options.preferredVersions,
|
||||
[options.currentPkg.name]: { [options.currentPkg.version]: 'version' },
|
||||
}
|
||||
: options.preferredVersions
|
||||
|
||||
const resolveResult = await ctx.requestsQueue.add<ResolveResult>(async () => ctx.resolve(wantedDependency, {
|
||||
alwaysTryWorkspacePackages: options.alwaysTryWorkspacePackages,
|
||||
defaultTag: options.defaultTag,
|
||||
publishedBy: options.publishedBy,
|
||||
pickLowestVersion: options.pickLowestVersion,
|
||||
lockfileDir: options.lockfileDir,
|
||||
preferredVersions: options.preferredVersions,
|
||||
preferredVersions,
|
||||
preferWorkspacePackages: options.preferWorkspacePackages,
|
||||
projectDir: options.projectDir,
|
||||
workspacePackages: options.workspacePackages,
|
||||
|
||||
@@ -1267,7 +1267,9 @@ async function resolveDependency (
|
||||
currentPkg: currentPkg
|
||||
? {
|
||||
id: currentPkg.pkgId,
|
||||
name: currentPkg.name,
|
||||
resolution: currentPkg.resolution,
|
||||
version: currentPkg.version,
|
||||
}
|
||||
: undefined,
|
||||
expectedPkg: currentPkg,
|
||||
|
||||
@@ -110,7 +110,9 @@ export interface RequestPackageOptions {
|
||||
alwaysTryWorkspacePackages?: boolean
|
||||
currentPkg?: {
|
||||
id?: PkgResolutionId
|
||||
name?: string
|
||||
resolution?: Resolution
|
||||
version?: string
|
||||
}
|
||||
/**
|
||||
* Expected package is the package name and version that are found in the lockfile.
|
||||
|
||||
Reference in New Issue
Block a user