mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-10 18:18:56 -04:00
fix: update on a subset of projects should work with dedupe-peer-dependents (#6178)
This commit is contained in:
6
.changeset/olive-falcons-share.md
Normal file
6
.changeset/olive-falcons-share.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/resolve-dependencies": major
|
||||
"@pnpm/core": major
|
||||
---
|
||||
|
||||
The update options are passed on per project basis. So the `update` and `updateMatching` options are options of importers/projects.
|
||||
@@ -14,3 +14,4 @@ export { ProjectOptions, UnexpectedStoreError, UnexpectedVirtualStoreDirError }
|
||||
export { InstallOptions } from './install/extendInstallOptions'
|
||||
|
||||
export { WorkspacePackages } from '@pnpm/resolver-base'
|
||||
export { UpdateMatchingFunction } from '@pnpm/resolve-dependencies'
|
||||
|
||||
@@ -54,9 +54,6 @@ export interface StrictInstallOptions {
|
||||
reporter: ReporterFunction
|
||||
force: boolean
|
||||
forcePublicHoistPattern: boolean
|
||||
update: boolean
|
||||
updateMatching?: (pkgName: string) => boolean
|
||||
updatePackageManifest?: boolean
|
||||
depth: number
|
||||
lockfileDir: string
|
||||
modulesDir: string
|
||||
@@ -196,7 +193,6 @@ const defaults = async (opts: InstallOptions) => {
|
||||
process.platform === 'cygwin' ||
|
||||
!process.setgid ||
|
||||
process.getuid() !== 0,
|
||||
update: false,
|
||||
useLockfile: true,
|
||||
saveLockfile: true,
|
||||
useGitBranchLockfile: false,
|
||||
|
||||
@@ -45,6 +45,7 @@ import {
|
||||
DependenciesGraphNode,
|
||||
PinnedVersion,
|
||||
resolveDependencies,
|
||||
UpdateMatchingFunction,
|
||||
WantedDependency,
|
||||
} from '@pnpm/resolve-dependencies'
|
||||
import {
|
||||
@@ -89,36 +90,50 @@ const BROKEN_LOCKFILE_INTEGRITY_ERRORS = new Set([
|
||||
|
||||
const DEV_PREINSTALL = 'pnpm:devPreinstall'
|
||||
|
||||
export type DependenciesMutation = (
|
||||
{
|
||||
mutation: 'install'
|
||||
pruneDirectDependencies?: boolean
|
||||
} | {
|
||||
allowNew?: boolean
|
||||
dependencySelectors: string[]
|
||||
mutation: 'installSome'
|
||||
peer?: boolean
|
||||
pruneDirectDependencies?: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
targetDependenciesField?: DependenciesField
|
||||
} | {
|
||||
mutation: 'uninstallSome'
|
||||
dependencyNames: string[]
|
||||
targetDependenciesField?: DependenciesField
|
||||
} | {
|
||||
mutation: 'unlink'
|
||||
} | {
|
||||
mutation: 'unlinkSome'
|
||||
dependencyNames: string[]
|
||||
}
|
||||
)
|
||||
interface InstallMutationOptions {
|
||||
update?: boolean
|
||||
updateMatching?: UpdateMatchingFunction
|
||||
updatePackageManifest?: boolean
|
||||
}
|
||||
|
||||
export interface InstallDepsMutation extends InstallMutationOptions {
|
||||
mutation: 'install'
|
||||
pruneDirectDependencies?: boolean
|
||||
}
|
||||
|
||||
export interface InstallSomeDepsMutation extends InstallMutationOptions {
|
||||
allowNew?: boolean
|
||||
dependencySelectors: string[]
|
||||
mutation: 'installSome'
|
||||
peer?: boolean
|
||||
pruneDirectDependencies?: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
targetDependenciesField?: DependenciesField
|
||||
}
|
||||
|
||||
export interface UninstallSomeDepsMutation {
|
||||
mutation: 'uninstallSome'
|
||||
dependencyNames: string[]
|
||||
targetDependenciesField?: DependenciesField
|
||||
}
|
||||
|
||||
export interface UnlinkDepsMutation {
|
||||
mutation: 'unlink'
|
||||
}
|
||||
|
||||
export interface UnlinkSomeDepsMutation {
|
||||
mutation: 'unlinkSome'
|
||||
dependencyNames: string[]
|
||||
}
|
||||
|
||||
export type DependenciesMutation = InstallDepsMutation | InstallSomeDepsMutation | UninstallSomeDepsMutation | UnlinkDepsMutation | UnlinkSomeDepsMutation
|
||||
|
||||
export async function install (
|
||||
manifest: ProjectManifest,
|
||||
opts: Omit<InstallOptions, 'allProjects'> & {
|
||||
preferredVersions?: PreferredVersions
|
||||
pruneDirectDependencies?: boolean
|
||||
}
|
||||
} & InstallMutationOptions
|
||||
) {
|
||||
const rootDir = opts.dir ?? process.cwd()
|
||||
const projects = await mutateModules(
|
||||
@@ -127,6 +142,9 @@ export async function install (
|
||||
mutation: 'install',
|
||||
pruneDirectDependencies: opts.pruneDirectDependencies,
|
||||
rootDir,
|
||||
update: opts.update,
|
||||
updateMatching: opts.updateMatching,
|
||||
updatePackageManifest: opts.updatePackageManifest,
|
||||
},
|
||||
],
|
||||
{
|
||||
@@ -165,10 +183,17 @@ export async function mutateModulesInSingleProject (
|
||||
rootDir: string
|
||||
modulesDir?: string
|
||||
},
|
||||
maybeOpts: Omit<MutateModulesOptions, 'allProjects'>
|
||||
maybeOpts: Omit<MutateModulesOptions, 'allProjects'> & InstallMutationOptions
|
||||
): Promise<UpdatedProject> {
|
||||
const [updatedProject] = await mutateModules(
|
||||
[project],
|
||||
[
|
||||
{
|
||||
...project,
|
||||
update: maybeOpts.update,
|
||||
updateMatching: maybeOpts.updateMatching,
|
||||
updatePackageManifest: maybeOpts.updatePackageManifest,
|
||||
} as MutatedProject,
|
||||
],
|
||||
{
|
||||
...maybeOpts,
|
||||
allProjects: [{
|
||||
@@ -195,7 +220,7 @@ export async function mutateModules (
|
||||
throw new PnpmError('OPTIONAL_DEPS_REQUIRE_PROD_DEPS', 'Optional dependencies cannot be installed without production dependencies')
|
||||
}
|
||||
|
||||
const installsOnly = projects.every((project) => project.mutation === 'install')
|
||||
const installsOnly = projects.every((project) => project.mutation === 'install' && !project.update && !project.updateMatching)
|
||||
if (!installsOnly) opts.strictPeerDependencies = false
|
||||
// @ts-expect-error
|
||||
opts['forceNewModules'] = installsOnly
|
||||
@@ -306,7 +331,6 @@ export async function mutateModules (
|
||||
opts.frozenLockfileIfExists && ctx.existsWantedLockfile
|
||||
if (
|
||||
!ctx.lockfileHadConflicts &&
|
||||
!opts.update &&
|
||||
!opts.fixLockfile &&
|
||||
!opts.dedupe &&
|
||||
installsOnly &&
|
||||
@@ -396,7 +420,9 @@ export async function mutateModules (
|
||||
if (BROKEN_LOCKFILE_INTEGRITY_ERRORS.has(error.code)) {
|
||||
needsFullResolution = true
|
||||
// Ideally, we would not update but currently there is no other way to redownload the integrity of the package
|
||||
opts.update = true
|
||||
for (const project of projects) {
|
||||
(project as InstallMutationOptions).update = true
|
||||
}
|
||||
}
|
||||
// A broken lockfile may be caused by a badly resolved Git conflict
|
||||
logger.warn({
|
||||
@@ -432,14 +458,14 @@ export async function mutateModules (
|
||||
case 'install': {
|
||||
await installCase({
|
||||
...projectOpts,
|
||||
updatePackageManifest: opts.updatePackageManifest ?? opts.update,
|
||||
updatePackageManifest: (projectOpts as InstallDepsMutation).updatePackageManifest ?? (projectOpts as InstallDepsMutation).update,
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'installSome': {
|
||||
await installSome({
|
||||
...projectOpts,
|
||||
updatePackageManifest: opts.updatePackageManifest !== false,
|
||||
updatePackageManifest: (projectOpts as InstallSomeDepsMutation).updatePackageManifest !== false,
|
||||
})
|
||||
break
|
||||
}
|
||||
@@ -510,7 +536,7 @@ export async function mutateModules (
|
||||
const wantedDependencies = getWantedDependencies(project.manifest, {
|
||||
autoInstallPeers: opts.autoInstallPeers,
|
||||
includeDirect: opts.includeDirect,
|
||||
updateWorkspaceDependencies: opts.update,
|
||||
updateWorkspaceDependencies: project.update,
|
||||
nodeExecPath: opts.nodeExecPath,
|
||||
})
|
||||
.map((wantedDependency) => ({ ...wantedDependency, updateSpec: true, preserveNonSemverVersionSpec: true }))
|
||||
@@ -549,7 +575,7 @@ export async function mutateModules (
|
||||
devDependencies,
|
||||
optional: project.targetDependenciesField === 'optionalDependencies',
|
||||
optionalDependencies,
|
||||
updateWorkspaceDependencies: opts.update,
|
||||
updateWorkspaceDependencies: project.update,
|
||||
preferredSpecs,
|
||||
overrides: opts.overrides,
|
||||
})
|
||||
@@ -684,7 +710,7 @@ export async function addDependenciesToPackage (
|
||||
peer?: boolean
|
||||
pinnedVersion?: 'major' | 'minor' | 'patch'
|
||||
targetDependenciesField?: DependenciesField
|
||||
}
|
||||
} & InstallMutationOptions
|
||||
) {
|
||||
const rootDir = opts.dir ?? process.cwd()
|
||||
const projects = await mutateModules(
|
||||
@@ -697,6 +723,9 @@ export async function addDependenciesToPackage (
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
rootDir,
|
||||
targetDependenciesField: opts.targetDependenciesField,
|
||||
update: opts.update,
|
||||
updateMatching: opts.updateMatching,
|
||||
updatePackageManifest: opts.updatePackageManifest,
|
||||
},
|
||||
],
|
||||
{
|
||||
@@ -798,8 +827,9 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
|
||||
stage: 'resolution_started',
|
||||
})
|
||||
|
||||
const update = projects.some((project) => (project as InstallMutationOptions).update)
|
||||
const preferredVersions = opts.preferredVersions ?? (
|
||||
!opts.update
|
||||
!update
|
||||
? getPreferredVersionsFromLockfileAndManifests(ctx.wantedLockfile.packages, Object.values(ctx.projects).map(({ manifest }) => manifest))
|
||||
: undefined
|
||||
)
|
||||
@@ -853,7 +883,7 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
|
||||
allowNonAppliedPatches: opts.allowNonAppliedPatches,
|
||||
autoInstallPeers: opts.autoInstallPeers,
|
||||
currentLockfile: ctx.currentLockfile,
|
||||
defaultUpdateDepth: (opts.update || (opts.updateMatching != null)) ? opts.depth : -1,
|
||||
defaultUpdateDepth: opts.depth,
|
||||
dedupePeerDependents: opts.dedupePeerDependents,
|
||||
dryRun: opts.lockfileOnly,
|
||||
engineStrict: opts.engineStrict,
|
||||
@@ -875,7 +905,6 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
|
||||
saveWorkspaceProtocol: opts.saveWorkspaceProtocol,
|
||||
storeController: opts.storeController,
|
||||
tag: opts.tag,
|
||||
updateMatching: opts.updateMatching,
|
||||
virtualStoreDir: ctx.virtualStoreDir,
|
||||
wantedLockfile: ctx.wantedLockfile,
|
||||
workspacePackages: opts.workspacePackages,
|
||||
@@ -1248,7 +1277,9 @@ const installInContext: InstallFunction = async (projects, ctx, opts) => {
|
||||
) throw error
|
||||
opts.needsFullResolution = true
|
||||
// Ideally, we would not update but currently there is no other way to redownload the integrity of the package
|
||||
opts.update = true
|
||||
for (const project of projects) {
|
||||
(project as InstallMutationOptions).update = true
|
||||
}
|
||||
logger.warn({
|
||||
error,
|
||||
message: error.message,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as path from 'path'
|
||||
import { promises as fs } from 'fs'
|
||||
import { prepareEmpty, preparePackages } from '@pnpm/prepare'
|
||||
import { prepareEmpty, prepare, preparePackages } from '@pnpm/prepare'
|
||||
import { PnpmError } from '@pnpm/error'
|
||||
import {
|
||||
PackageManifestLog,
|
||||
@@ -716,6 +716,7 @@ test('lockfile locks npm dependencies', async () => {
|
||||
const reporter = sinon.spy()
|
||||
|
||||
await addDistTag({ package: '@pnpm.e2e/dep-of-pkg-with-1-dep', version: '100.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/pkg-with-1-dep', version: '100.0.0', distTag: 'latest' })
|
||||
|
||||
const manifest = await addDependenciesToPackage({}, ['@pnpm.e2e/pkg-with-1-dep'], await testDefaults({ save: true, reporter }))
|
||||
|
||||
@@ -815,7 +816,7 @@ test('should throw error when trying to install a package without name', async (
|
||||
|
||||
// Covers https://github.com/pnpm/pnpm/issues/1193
|
||||
test('rewrites node_modules created by npm', async () => {
|
||||
const project = prepareEmpty()
|
||||
const project = prepare()
|
||||
|
||||
await execa('npm', ['install', 'rimraf@2.5.1', '@types/node', '--save'])
|
||||
|
||||
@@ -1004,6 +1005,7 @@ test('all the subdeps of dependencies are linked when a node_modules is partiall
|
||||
|
||||
test('subdep symlinks are updated if the lockfile has new subdep versions specified', async () => {
|
||||
await addDistTag({ package: '@pnpm.e2e/dep-of-pkg-with-1-dep', version: '100.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/pkg-with-1-dep', version: '100.0.0', distTag: 'latest' })
|
||||
const project = prepareEmpty()
|
||||
|
||||
await mutateModulesInSingleProject({
|
||||
|
||||
@@ -927,10 +927,12 @@ test('update workspace range', async () => {
|
||||
dependencySelectors: ['dep1', 'dep2', 'dep3', 'dep4', 'dep5', 'dep6'],
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('project-1'),
|
||||
update: true,
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
update: true,
|
||||
},
|
||||
], await testDefaults({
|
||||
allProjects: [
|
||||
@@ -972,7 +974,6 @@ test('update workspace range', async () => {
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
],
|
||||
update: true,
|
||||
workspacePackages: {
|
||||
dep1: {
|
||||
'2.0.0': {
|
||||
@@ -1071,10 +1072,12 @@ test('update workspace range when save-workspace-protocol is "rolling"', async (
|
||||
dependencySelectors: ['dep1', 'dep2', 'dep3', 'dep4', 'dep5', 'dep6'],
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('project-1'),
|
||||
update: true,
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
update: true,
|
||||
},
|
||||
], await testDefaults({
|
||||
allProjects: [
|
||||
@@ -1113,7 +1116,6 @@ test('update workspace range when save-workspace-protocol is "rolling"', async (
|
||||
},
|
||||
],
|
||||
saveWorkspaceProtocol: 'rolling',
|
||||
update: true,
|
||||
workspacePackages: {
|
||||
dep1: {
|
||||
'2.0.0': {
|
||||
|
||||
@@ -184,6 +184,7 @@ test('multiple save to package.json with `exact` versions (@rstacruz/tap-spec &
|
||||
})
|
||||
|
||||
test('save to package.json with save prefix ~', async () => {
|
||||
await addDistTag({ package: '@pnpm.e2e/pkg-with-1-dep', version: '100.0.0', distTag: 'latest' })
|
||||
prepareEmpty()
|
||||
const manifest = await addDependenciesToPackage({}, ['@pnpm.e2e/pkg-with-1-dep'], await testDefaults({ pinnedVersion: 'minor' }))
|
||||
|
||||
@@ -211,10 +212,9 @@ test('an update bumps the versions in the manifest', async () => {
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
await testDefaults({
|
||||
update: true,
|
||||
}))
|
||||
},
|
||||
await testDefaults())
|
||||
|
||||
expect(manifest).toStrictEqual({
|
||||
dependencies: {
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
MutatedProject,
|
||||
mutateModules,
|
||||
ProjectOptions,
|
||||
UpdateMatchingFunction,
|
||||
WorkspacePackages,
|
||||
} from '@pnpm/core'
|
||||
import isSubdir from 'is-subdir'
|
||||
@@ -79,6 +80,8 @@ type RecursiveOptions = CreateStoreControllerOptions & Pick<Config,
|
||||
forcePublicHoistPattern?: boolean
|
||||
ignoredPackages?: Set<string>
|
||||
update?: boolean
|
||||
updatePackageManifest?: boolean
|
||||
updateMatching?: UpdateMatchingFunction
|
||||
useBetaCli?: boolean
|
||||
allProjectsGraph: ProjectsGraph
|
||||
selectedProjectsGraph: ProjectsGraph
|
||||
@@ -234,6 +237,9 @@ export async function recursive (
|
||||
}),
|
||||
rootDir,
|
||||
targetDependenciesField,
|
||||
update: opts.update,
|
||||
updateMatching: opts.updateMatching,
|
||||
updatePackageManifest: opts.updatePackageManifest,
|
||||
} as MutatedProject)
|
||||
return
|
||||
case 'install':
|
||||
@@ -242,6 +248,9 @@ export async function recursive (
|
||||
mutation,
|
||||
pruneDirectDependencies: opts.pruneDirectDependencies,
|
||||
rootDir,
|
||||
update: opts.update,
|
||||
updateMatching: opts.updateMatching,
|
||||
updatePackageManifest: opts.updatePackageManifest,
|
||||
} as MutatedProject)
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -26,7 +26,7 @@ import promiseShare from 'promise-share'
|
||||
import difference from 'ramda/src/difference'
|
||||
import { getWantedDependencies, WantedDependency } from './getWantedDependencies'
|
||||
import { depPathToRef } from './depPathToRef'
|
||||
import { createNodeIdForLinkedLocalPkg } from './resolveDependencies'
|
||||
import { createNodeIdForLinkedLocalPkg, UpdateMatchingFunction } from './resolveDependencies'
|
||||
import {
|
||||
Importer,
|
||||
LinkedDependency,
|
||||
@@ -53,6 +53,7 @@ export {
|
||||
LinkedDependency,
|
||||
ResolvedPackage,
|
||||
PinnedVersion,
|
||||
UpdateMatchingFunction,
|
||||
WantedDependency,
|
||||
}
|
||||
|
||||
@@ -81,6 +82,8 @@ export type ImporterToResolve = Importer<{
|
||||
binsDir: string
|
||||
manifest: ProjectManifest
|
||||
originalManifest?: ProjectManifest
|
||||
update?: boolean
|
||||
updateMatching?: UpdateMatchingFunction
|
||||
updatePackageManifest: boolean
|
||||
targetDependenciesField?: DependenciesField
|
||||
}
|
||||
@@ -100,7 +103,6 @@ export async function resolveDependencies (
|
||||
defaultUpdateDepth: opts.defaultUpdateDepth,
|
||||
lockfileOnly: opts.dryRun,
|
||||
preferredVersions: opts.preferredVersions,
|
||||
updateAll: Boolean(opts.updateMatching),
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
workspacePackages: opts.workspacePackages,
|
||||
})
|
||||
|
||||
@@ -159,7 +159,6 @@ export interface ResolutionContext {
|
||||
registries: Registries
|
||||
resolutionMode?: 'highest' | 'time-based' | 'lowest-direct'
|
||||
virtualStoreDir: string
|
||||
updateMatching?: (pkgName: string) => boolean
|
||||
useLockfileV6?: boolean
|
||||
workspacePackages?: WorkspacePackages
|
||||
missingPeersOfChildrenByPkgId: Record<string, { parentImporterId: string, missingPeersOfChildren: MissingPeersOfChildren }>
|
||||
@@ -240,6 +239,8 @@ type ParentPkg = Pick<PkgAddress, 'nodeId' | 'installable' | 'depPath' | 'rootDi
|
||||
|
||||
export type ParentPkgAliases = Record<string, PkgAddress | true>
|
||||
|
||||
export type UpdateMatchingFunction = (pkgName: string) => boolean
|
||||
|
||||
interface ResolvedDependenciesOptions {
|
||||
currentDepth: number
|
||||
parentPkg: ParentPkg
|
||||
@@ -252,6 +253,7 @@ interface ResolvedDependenciesOptions {
|
||||
publishedBy?: Date
|
||||
pickLowestVersion?: boolean
|
||||
resolvedDependencies?: ResolvedDependencies
|
||||
updateMatching?: UpdateMatchingFunction
|
||||
updateDepth: number
|
||||
prefix: string
|
||||
}
|
||||
@@ -647,8 +649,8 @@ async function resolveDependenciesOfDependency (
|
||||
const update = ((extendedWantedDep.infoFromLockfile?.dependencyLockfile) == null) ||
|
||||
(
|
||||
updateShouldContinue && (
|
||||
(ctx.updateMatching == null) ||
|
||||
ctx.updateMatching(extendedWantedDep.infoFromLockfile.name!)
|
||||
(options.updateMatching == null) ||
|
||||
options.updateMatching(extendedWantedDep.infoFromLockfile.name!)
|
||||
)
|
||||
) || Boolean(
|
||||
(ctx.workspacePackages != null) &&
|
||||
@@ -672,6 +674,7 @@ async function resolveDependenciesOfDependency (
|
||||
publishedBy: options.publishedBy,
|
||||
update,
|
||||
updateDepth,
|
||||
updateMatching: options.updateMatching,
|
||||
}
|
||||
const resolveDependencyResult = await resolveDependency(extendedWantedDep.wantedDependency, ctx, resolveDependencyOpts)
|
||||
|
||||
@@ -706,6 +709,7 @@ async function resolveDependenciesOfDependency (
|
||||
parentDepth: options.currentDepth,
|
||||
updateDepth,
|
||||
prefix: options.prefix,
|
||||
updateMatching: options.updateMatching,
|
||||
})
|
||||
return {
|
||||
resolveDependencyResult,
|
||||
@@ -751,6 +755,7 @@ async function resolveChildren (
|
||||
dependencyLockfile,
|
||||
parentDepth,
|
||||
updateDepth,
|
||||
updateMatching,
|
||||
prefix,
|
||||
}: {
|
||||
parentPkg: PkgAddress
|
||||
@@ -758,6 +763,7 @@ async function resolveChildren (
|
||||
parentDepth: number
|
||||
updateDepth: number
|
||||
prefix: string
|
||||
updateMatching?: UpdateMatchingFunction
|
||||
},
|
||||
{
|
||||
parentPkgAliases,
|
||||
@@ -802,6 +808,7 @@ async function resolveChildren (
|
||||
publishedBy,
|
||||
resolvedDependencies,
|
||||
updateDepth,
|
||||
updateMatching,
|
||||
}
|
||||
)
|
||||
ctx.childrenByParentDepPath[parentPkg.depPath] = pkgAddresses.map((child) => ({
|
||||
@@ -1001,6 +1008,7 @@ interface ResolveDependencyOptions {
|
||||
pickLowestVersion?: boolean
|
||||
update: boolean
|
||||
updateDepth: number
|
||||
updateMatching?: UpdateMatchingFunction
|
||||
}
|
||||
|
||||
type ResolveDependencyResult = PkgAddress | LinkedDependency | null
|
||||
|
||||
@@ -52,6 +52,7 @@ export interface Importer<T> {
|
||||
|
||||
export interface ImporterToResolveGeneric<T> extends Importer<T> {
|
||||
updatePackageManifest: boolean
|
||||
updateMatching?: (pkgName: string) => boolean
|
||||
hasRemovedDependencies?: boolean
|
||||
preferredVersions?: PreferredVersions
|
||||
wantedDependencies: Array<T & WantedDependency & { updateDepth: number }>
|
||||
@@ -79,7 +80,6 @@ export interface ResolveDependenciesOptions {
|
||||
preferWorkspacePackages?: boolean
|
||||
resolutionMode?: 'highest' | 'time-based' | 'lowest-direct'
|
||||
resolvePeersFromWorkspaceRoot?: boolean
|
||||
updateMatching?: (pkgName: string) => boolean
|
||||
linkWorkspacePackagesDepth?: number
|
||||
lockfileDir: string
|
||||
storeController: StoreController
|
||||
@@ -122,7 +122,6 @@ export async function resolveDependencyTree<T> (
|
||||
resolutionMode: opts.resolutionMode,
|
||||
skipped: wantedToBeSkippedPackageIds,
|
||||
storeController: opts.storeController,
|
||||
updateMatching: opts.updateMatching,
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
wantedLockfile: opts.wantedLockfile,
|
||||
appliedPatches: new Set<string>(),
|
||||
@@ -154,6 +153,7 @@ export async function resolveDependencyTree<T> (
|
||||
...projectSnapshot.optionalDependencies,
|
||||
},
|
||||
updateDepth: -1,
|
||||
updateMatching: importer.updateMatching,
|
||||
prefix: importer.rootDir,
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -15,7 +15,6 @@ export async function toResolveImporter (
|
||||
defaultUpdateDepth: number
|
||||
lockfileOnly: boolean
|
||||
preferredVersions?: PreferredVersions
|
||||
updateAll: boolean
|
||||
virtualStoreDir: string
|
||||
workspacePackages: WorkspacePackages
|
||||
},
|
||||
@@ -29,6 +28,7 @@ export async function toResolveImporter (
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
workspacePackages: opts.workspacePackages,
|
||||
})
|
||||
const defaultUpdateDepth = (project.update === true || (project.updateMatching != null)) ? opts.defaultUpdateDepth : -1
|
||||
const existingDeps = nonLinkedDependencies
|
||||
.filter(({ alias }) => !project.wantedDependencies.some((wantedDep) => wantedDep.alias === alias))
|
||||
let wantedDependencies!: Array<WantedDependency & { isNew?: boolean, updateDepth: number }>
|
||||
@@ -39,22 +39,22 @@ export async function toResolveImporter (
|
||||
]
|
||||
.map((dep) => ({
|
||||
...dep,
|
||||
updateDepth: opts.defaultUpdateDepth,
|
||||
updateDepth: defaultUpdateDepth,
|
||||
}))
|
||||
} else {
|
||||
// Direct local tarballs are always checked,
|
||||
// so their update depth should be at least 0
|
||||
const updateLocalTarballs = (dep: WantedDependency) => ({
|
||||
...dep,
|
||||
updateDepth: opts.updateAll
|
||||
? opts.defaultUpdateDepth
|
||||
updateDepth: project.updateMatching != null
|
||||
? defaultUpdateDepth
|
||||
: (prefIsLocalTarball(dep.pref) ? 0 : -1),
|
||||
})
|
||||
wantedDependencies = [
|
||||
...project.wantedDependencies.map(
|
||||
opts.defaultUpdateDepth < 0
|
||||
defaultUpdateDepth < 0
|
||||
? updateLocalTarballs
|
||||
: (dep) => ({ ...dep, updateDepth: opts.defaultUpdateDepth })),
|
||||
: (dep) => ({ ...dep, updateDepth: defaultUpdateDepth })),
|
||||
...existingDeps.map(updateLocalTarballs),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { preparePackages } from '@pnpm/prepare'
|
||||
import { addDistTag } from '@pnpm/registry-mock'
|
||||
import { sync as readYamlFile } from 'read-yaml-file'
|
||||
import { createPeersFolderSuffix } from '@pnpm/dependency-path'
|
||||
import { sync as loadJsonFile } from 'load-json-file'
|
||||
import { sync as writeYamlFile } from 'write-yaml-file'
|
||||
import { execPnpm } from '../utils'
|
||||
|
||||
@@ -46,3 +47,46 @@ auto-install-peers=false`, 'utf8')
|
||||
expect(depPaths).toContain(`/@pnpm.e2e/abc/1.0.0${createPeersFolderSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
|
||||
expect(depPaths).toContain(`/@pnpm.e2e/abc-parent-with-ab/1.0.0${createPeersFolderSuffix([{ name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
|
||||
})
|
||||
|
||||
test('partial update in a workspace should work with dedupe-peer-dependents is true', async () => {
|
||||
await addDistTag({ package: '@pnpm.e2e/abc-parent-with-ab', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/abc', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-a', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-b', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-c', version: '1.0.0', distTag: 'latest' })
|
||||
|
||||
preparePackages([
|
||||
{
|
||||
location: 'project-1',
|
||||
package: {
|
||||
name: 'project-1',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/abc-grand-parent-with-c': '^1.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
location: 'project-2',
|
||||
package: {
|
||||
name: 'project-2',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/abc-grand-parent-with-c': '^1.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'] })
|
||||
writeFileSync('.npmrc', `dedupe-peer-dependents=true
|
||||
auto-install-peers=false`, 'utf8')
|
||||
await execPnpm(['install'])
|
||||
await addDistTag({ package: '@pnpm.e2e/abc-parent-with-ab', version: '1.0.1', distTag: 'latest' })
|
||||
process.chdir('project-2')
|
||||
await execPnpm(['update'])
|
||||
process.chdir('..')
|
||||
|
||||
expect(loadJsonFile<any>('project-1/package.json').dependencies['@pnpm.e2e/abc-grand-parent-with-c']).toBe('^1.0.0') // eslint-disable-line
|
||||
expect(loadJsonFile<any>('project-2/package.json').dependencies['@pnpm.e2e/abc-grand-parent-with-c']).toBe('^1.0.1') // eslint-disable-line
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user