mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-10 18:18:56 -04:00
5
.changeset/dry-bobcats-yawn.md
Normal file
5
.changeset/dry-bobcats-yawn.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-installation": minor
|
||||
---
|
||||
|
||||
Allow to update specific packages up until a specified depth. For instance, `pnpm update @types/* --depth Infinity`.
|
||||
6
.changeset/few-flies-hunt.md
Normal file
6
.changeset/few-flies-hunt.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/resolve-dependencies": minor
|
||||
"supi": minor
|
||||
---
|
||||
|
||||
New option added: updateMatching. updateMatching is a function that accepts a package name. It returns `true` if the specified package should be updated.
|
||||
@@ -243,6 +243,7 @@ export type InstallCommandOptions = Pick<Config,
|
||||
| 'bail'
|
||||
| 'bin'
|
||||
| 'cliOptions'
|
||||
| 'depth'
|
||||
| 'dev'
|
||||
| 'engineStrict'
|
||||
| 'global'
|
||||
|
||||
@@ -31,6 +31,7 @@ export type InstallDepsOptions = Pick<Config,
|
||||
| 'bail'
|
||||
| 'bin'
|
||||
| 'cliOptions'
|
||||
| 'depth'
|
||||
| 'dev'
|
||||
| 'engineStrict'
|
||||
| 'global'
|
||||
@@ -71,6 +72,7 @@ export type InstallDepsOptions = Pick<Config,
|
||||
includeDirect?: IncludedDependencies,
|
||||
latest?: boolean,
|
||||
update?: boolean,
|
||||
updateMatching?: (pkgName: string) => boolean,
|
||||
updatePackageManifest?: boolean,
|
||||
useBetaCli?: boolean,
|
||||
recursive?: boolean,
|
||||
|
||||
@@ -42,6 +42,7 @@ import { createWorkspaceSpecs, updateToWorkspacePackagesFromManifest } from './u
|
||||
|
||||
type RecursiveOptions = CreateStoreControllerOptions & Pick<Config,
|
||||
| 'bail'
|
||||
| 'depth'
|
||||
| 'globalPnpmfile'
|
||||
| 'hoistPattern'
|
||||
| 'ignorePnpmfile'
|
||||
@@ -178,7 +179,7 @@ export default async function recursive (
|
||||
let currentInput = [...params]
|
||||
if (updateMatch) {
|
||||
currentInput = matchDependencies(updateMatch, manifest, includeDirect)
|
||||
if (!currentInput.length) {
|
||||
if (!currentInput.length && (typeof opts.depth === 'undefined' || opts.depth <= 0)) {
|
||||
installOpts.pruneLockfileImporters = false
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
import { CompletionFunc } from '@pnpm/command'
|
||||
import { FILTERING, OPTIONS, UNIVERSAL_OPTIONS } from '@pnpm/common-cli-options-help'
|
||||
import { types as allTypes } from '@pnpm/config'
|
||||
import matcher from '@pnpm/matcher'
|
||||
import { outdatedDepsOfProjects } from '@pnpm/outdated'
|
||||
import chalk = require('chalk')
|
||||
import { prompt } from 'enquirer'
|
||||
@@ -234,6 +235,8 @@ async function update (
|
||||
allowNew: false,
|
||||
includeDirect,
|
||||
update: true,
|
||||
updateMatching: dependencies.every(dep => !dep.substring(1).includes('@')) && opts.depth && opts.depth > 0 && !opts.latest
|
||||
? matcher(dependencies) : undefined,
|
||||
updatePackageManifest: opts.save !== false,
|
||||
}, dependencies)
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ export default async function (
|
||||
nodeVersion: string,
|
||||
registries: Registries,
|
||||
pnpmVersion: string,
|
||||
updateMatching?: (pkgName: string) => boolean,
|
||||
linkWorkspacePackagesDepth?: number,
|
||||
lockfileDir: string,
|
||||
storeController: StoreController,
|
||||
@@ -91,6 +92,7 @@ export default async function (
|
||||
resolvedPackagesByPackageId: {} as ResolvedPackagesByPackageId,
|
||||
skipped: wantedToBeSkippedPackageIds,
|
||||
storeController: opts.storeController,
|
||||
updateMatching: opts.updateMatching,
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
wantedLockfile: opts.wantedLockfile,
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ export interface ResolutionContext {
|
||||
pnpmVersion: string,
|
||||
registries: Registries,
|
||||
virtualStoreDir: string,
|
||||
updateMatching?: (pkgName: string) => boolean,
|
||||
}
|
||||
|
||||
export type PkgAddress = {
|
||||
@@ -240,11 +241,17 @@ export default async function resolveDependencies (
|
||||
.map(async (extendedWantedDep) => {
|
||||
const updateDepth = typeof extendedWantedDep.wantedDependency.updateDepth === 'number'
|
||||
? extendedWantedDep.wantedDependency.updateDepth : options.updateDepth
|
||||
const updateShouldContinue = options.currentDepth <= updateDepth
|
||||
const update = updateShouldContinue && (
|
||||
!ctx.updateMatching ||
|
||||
!extendedWantedDep.infoFromLockfile?.dependencyLockfile ||
|
||||
ctx.updateMatching(extendedWantedDep.infoFromLockfile.dependencyLockfile.name ?? extendedWantedDep.wantedDependency.alias)
|
||||
)
|
||||
const resolveDependencyOpts: ResolveDependencyOptions = {
|
||||
...resolveDepOpts,
|
||||
currentPkg: extendedWantedDep.infoFromLockfile ?? undefined,
|
||||
proceed: extendedWantedDep.proceed,
|
||||
update: options.currentDepth <= updateDepth,
|
||||
proceed: extendedWantedDep.proceed || updateShouldContinue,
|
||||
update,
|
||||
updateDepth,
|
||||
}
|
||||
const resolveDependencyResult = await resolveDependency(extendedWantedDep.wantedDependency, ctx, resolveDependencyOpts)
|
||||
@@ -430,13 +437,13 @@ function getInfoFromLockfile (
|
||||
lockfile: Lockfile,
|
||||
registries: Registries,
|
||||
reference: string | undefined,
|
||||
pkgName: string | undefined
|
||||
alias: string | undefined
|
||||
) {
|
||||
if (!reference || !pkgName) {
|
||||
if (!reference || !alias) {
|
||||
return null
|
||||
}
|
||||
|
||||
const depPath = dp.refToRelative(reference, pkgName)
|
||||
const depPath = dp.refToRelative(reference, alias)
|
||||
|
||||
if (!depPath) {
|
||||
return null
|
||||
@@ -602,6 +609,10 @@ async function resolveDependency (
|
||||
let useManifestInfoFromLockfile = false
|
||||
let prepare!: boolean
|
||||
let hasBin!: boolean
|
||||
pkg = ctx.readPackageHook
|
||||
? ctx.readPackageHook(pkgResponse.body.manifest || await pkgResponse.bundledManifest!())
|
||||
: pkgResponse.body.manifest || await pkgResponse.bundledManifest!()
|
||||
|
||||
if (
|
||||
!options.update && currentPkg.dependencyLockfile && currentPkg.depPath &&
|
||||
!pkgResponse.body.updated &&
|
||||
@@ -613,16 +624,13 @@ async function resolveDependency (
|
||||
useManifestInfoFromLockfile = true
|
||||
prepare = currentPkg.dependencyLockfile.prepare === true
|
||||
hasBin = currentPkg.dependencyLockfile.hasBin === true
|
||||
pkg = Object.assign(
|
||||
nameVerFromPkgSnapshot(currentPkg.depPath, currentPkg.dependencyLockfile),
|
||||
currentPkg.dependencyLockfile
|
||||
)
|
||||
pkg = {
|
||||
...nameVerFromPkgSnapshot(currentPkg.depPath, currentPkg.dependencyLockfile),
|
||||
...currentPkg.dependencyLockfile,
|
||||
...pkg,
|
||||
}
|
||||
} else {
|
||||
// tslint:disable:no-string-literal
|
||||
pkg = ctx.readPackageHook
|
||||
? ctx.readPackageHook(pkgResponse.body.manifest || await pkgResponse.bundledManifest!())
|
||||
: pkgResponse.body.manifest || await pkgResponse.bundledManifest!()
|
||||
|
||||
prepare = Boolean(
|
||||
pkgResponse.body.resolvedVia === 'git-repository' &&
|
||||
typeof pkg.scripts?.prepare === 'string'
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface StrictInstallOptions {
|
||||
reporter: ReporterFunction,
|
||||
force: boolean,
|
||||
update: boolean,
|
||||
updateMatching?: (pkgName: string) => boolean,
|
||||
updatePackageManifest: boolean,
|
||||
depth: number,
|
||||
lockfileDir: string,
|
||||
|
||||
@@ -597,10 +597,11 @@ async function installInContext (
|
||||
|| !opts.currentLockfileIsUpToDate
|
||||
|| opts.force
|
||||
const _toResolveImporter = toResolveImporter.bind(null, {
|
||||
defaultUpdateDepth: opts.update ? opts.depth : -1,
|
||||
defaultUpdateDepth: (opts.update || opts.updateMatching) ? opts.depth : -1,
|
||||
lockfileOnly: opts.lockfileOnly,
|
||||
preferredVersions,
|
||||
storeDir: ctx.storeDir,
|
||||
updateAll: Boolean(opts.updateMatching),
|
||||
virtualStoreDir: ctx.virtualStoreDir,
|
||||
workspacePackages: opts.workspacePackages,
|
||||
})
|
||||
@@ -627,6 +628,7 @@ async function installInContext (
|
||||
registries: opts.registries,
|
||||
storeController: opts.storeController,
|
||||
tag: opts.tag,
|
||||
updateMatching: opts.updateMatching,
|
||||
virtualStoreDir: ctx.virtualStoreDir,
|
||||
wantedLockfile: ctx.wantedLockfile,
|
||||
workspacePackages: opts.workspacePackages,
|
||||
@@ -839,6 +841,7 @@ async function toResolveImporter (
|
||||
lockfileOnly: boolean,
|
||||
preferredVersions?: PreferredVersions,
|
||||
storeDir: string,
|
||||
updateAll: boolean,
|
||||
virtualStoreDir: string,
|
||||
workspacePackages: WorkspacePackages,
|
||||
},
|
||||
@@ -870,7 +873,8 @@ async function toResolveImporter (
|
||||
// so their update depth should be at least 0
|
||||
const updateLocalTarballs = (dep: WantedDependency) => ({
|
||||
...dep,
|
||||
updateDepth: prefIsLocalTarball(dep.pref) ? 0 : -1,
|
||||
updateDepth: opts.updateAll ?
|
||||
opts.defaultUpdateDepth : (prefIsLocalTarball(dep.pref) ? 0 : -1),
|
||||
})
|
||||
wantedDependencies = [
|
||||
...project.wantedDependencies.map(
|
||||
|
||||
@@ -990,7 +990,7 @@ test('all the subdeps of dependencies are linked when a node_modules is partiall
|
||||
'bar',
|
||||
'foo',
|
||||
'foobarqar',
|
||||
'is-positive',
|
||||
'qar',
|
||||
]
|
||||
)
|
||||
})
|
||||
|
||||
@@ -180,3 +180,43 @@ test('update only the packages that were requested to be updated when hoisting i
|
||||
const lockfile = await project.readLockfile()
|
||||
t.deepEqual(Object.keys(lockfile.packages), ['/bar/100.0.0', '/foo/100.1.0'])
|
||||
})
|
||||
|
||||
test('update only the specified package', async (t: tape.Test) => {
|
||||
const project = prepareEmpty(t)
|
||||
|
||||
await Promise.all([
|
||||
addDistTag('abc-grand-parent-with-c', '1.0.0', 'latest'),
|
||||
addDistTag('abc-parent-with-ab', '1.0.0', 'latest'),
|
||||
addDistTag('bar', '100.0.0', 'latest'),
|
||||
addDistTag('foo', '100.0.0', 'latest'),
|
||||
addDistTag('foobarqar', '1.0.0', 'latest'),
|
||||
addDistTag('peer-c', '1.0.0', 'latest'),
|
||||
])
|
||||
|
||||
const manifest = await addDependenciesToPackage({}, ['foobarqar', 'abc-grand-parent-with-c'], await testDefaults())
|
||||
|
||||
await Promise.all([
|
||||
addDistTag('abc-grand-parent-with-c', '1.0.1', 'latest'),
|
||||
addDistTag('abc-parent-with-ab', '1.0.1', 'latest'),
|
||||
addDistTag('bar', '100.1.0', 'latest'),
|
||||
addDistTag('foo', '100.1.0', 'latest'),
|
||||
addDistTag('foobarqar', '1.0.1', 'latest'),
|
||||
])
|
||||
|
||||
await install(manifest, await testDefaults({
|
||||
depth: Infinity,
|
||||
update: true,
|
||||
updateMatching: (pkgName: string) => pkgName === 'foo',
|
||||
}))
|
||||
|
||||
const lockfile = await project.readLockfile()
|
||||
|
||||
t.ok(lockfile.packages)
|
||||
t.ok(lockfile.packages['/abc-parent-with-ab/1.0.0_peer-c@1.0.0'], 'preserve version of package that has resolved peer deps')
|
||||
t.ok(lockfile.packages['/foobarqar/1.0.0'])
|
||||
t.deepEqual(lockfile.packages['/foobarqar/1.0.0'].dependencies, {
|
||||
bar: '100.0.0',
|
||||
foo: '100.1.0',
|
||||
'is-positive': '3.1.0',
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user