Skip to content

Commit c601040

Browse files
committed
Cherry-picks part of #4218
1 parent b400ff2 commit c601040

File tree

2 files changed

+58
-8
lines changed

2 files changed

+58
-8
lines changed

packages/plugin-patch/sources/commands/patchCommit.ts

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {BaseCommand, WorkspaceRequiredError} from '@yarnpkg/cli';
2-
import {Configuration, Project, structUtils} from '@yarnpkg/core';
2+
import {Configuration, Descriptor, DescriptorHash, Project, structUtils} from '@yarnpkg/core';
33
import {npath, xfs, ppath, PortablePath, Filename} from '@yarnpkg/fslib';
44
import {Command, Option, Usage, UsageError} from 'clipanion';
55

@@ -63,12 +63,54 @@ export default class PatchCommitCommand extends BaseCommand {
6363
await xfs.mkdirPromise(patchFolder, {recursive: true});
6464
await xfs.writeFilePromise(patchPath, diff);
6565

66-
const relPath = ppath.relative(project.cwd, patchPath);
66+
const transitiveDependencies = new Map<DescriptorHash, Descriptor>();
6767

68-
project.topLevelWorkspace.manifest.resolutions.push({
69-
pattern: {descriptor: {fullName: structUtils.stringifyIdent(locator), description: meta.version}},
70-
reference: `patch:${structUtils.stringifyLocator(locator)}#${relPath}`,
71-
});
68+
for (const pkg of project.storedPackages.values()) {
69+
if (structUtils.isVirtualLocator(pkg))
70+
continue;
71+
72+
const descriptor = pkg.dependencies.get(locator.identHash);
73+
if (!descriptor)
74+
continue;
75+
76+
const devirtualizedDescriptor = structUtils.isVirtualDescriptor(descriptor)
77+
? structUtils.devirtualizeDescriptor(descriptor)
78+
: descriptor;
79+
80+
const unpatchedDescriptor = patchUtils.ensureUnpatchedDescriptor(devirtualizedDescriptor);
81+
82+
const resolution = project.storedResolutions.get(unpatchedDescriptor.descriptorHash);
83+
if (!resolution)
84+
throw new Error(`Assertion failed: Expected the resolution to have been registered`);
85+
86+
const dependency = project.storedPackages.get(resolution);
87+
if (!dependency)
88+
throw new Error(`Assertion failed: Expected the package to have been registered`);
89+
90+
const originalPkg = project.originalPackages.get(pkg.locatorHash);
91+
if (!originalPkg)
92+
throw new Error(`Assertion failed: Expected the original package to have been registered`);
93+
94+
const originalDependency = originalPkg.dependencies.get(descriptor.identHash);
95+
if (!originalDependency)
96+
throw new Error(`Assertion failed: Expected the original dependency to have been registered`);
97+
98+
transitiveDependencies.set(originalDependency.descriptorHash, originalDependency);
99+
}
100+
101+
for (const originalDescriptor of transitiveDependencies.values()) {
102+
const newDescriptor = patchUtils.makeDescriptor(originalDescriptor, {
103+
parentLocator: null,
104+
sourceDescriptor: structUtils.convertLocatorToDescriptor(locator),
105+
sourceVersion: null,
106+
patchPaths: [`./${ppath.relative(project.cwd, patchPath)}` as PortablePath],
107+
});
108+
109+
project.topLevelWorkspace.manifest.resolutions.push({
110+
pattern: {descriptor: {fullName: structUtils.stringifyIdent(newDescriptor), description: originalDescriptor.range}},
111+
reference: newDescriptor.range,
112+
});
113+
}
72114

73115
await project.persist();
74116
}

packages/plugin-patch/sources/patchUtils.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ export function parseLocator(locator: Locator) {
4040
return {...rest, sourceLocator: sourceItem};
4141
}
4242

43+
export function ensureUnpatchedDescriptor(descriptor: Descriptor) {
44+
if (!descriptor.range.startsWith(`patch:`))
45+
return descriptor;
46+
47+
const {sourceItem} = parseSpec(descriptor.range, structUtils.parseDescriptor);
48+
return sourceItem;
49+
}
50+
4351
function makeSpec<T>({parentLocator, sourceItem, patchPaths, sourceVersion, patchHash}: {parentLocator: Locator | null, sourceItem: T, patchPaths: Array<PortablePath>, sourceVersion?: string | null, patchHash?: string}, sourceStringifier: (source: T) => string) {
4452
const parentLocatorSpread = parentLocator !== null
4553
? {locator: structUtils.stringifyLocator(parentLocator)}
@@ -66,10 +74,10 @@ function makeSpec<T>({parentLocator, sourceItem, patchPaths, sourceVersion, patc
6674
}
6775

6876
export function makeDescriptor(ident: Ident, {parentLocator, sourceDescriptor, patchPaths}: ReturnType<typeof parseDescriptor>) {
69-
return structUtils.makeLocator(ident, makeSpec({parentLocator, sourceItem: sourceDescriptor, patchPaths}, structUtils.stringifyDescriptor));
77+
return structUtils.makeDescriptor(ident, makeSpec({parentLocator, sourceItem: sourceDescriptor, patchPaths}, structUtils.stringifyDescriptor));
7078
}
7179

72-
export function makeLocator(ident: Ident, {parentLocator, sourcePackage, patchPaths, patchHash}: Omit<ReturnType<typeof parseLocator>, 'sourceLocator' | 'sourceVersion'> & {sourcePackage: Package, patchHash: string}) {
80+
export function makeLocator(ident: Ident, {parentLocator, sourcePackage, patchPaths, patchHash}: Omit<ReturnType<typeof parseLocator>, 'sourceLocator' | 'sourceVersion'> & {sourcePackage: Package, patchHash: string}) {
7381
return structUtils.makeLocator(ident, makeSpec({parentLocator, sourceItem: sourcePackage, sourceVersion: sourcePackage.version, patchPaths, patchHash}, structUtils.stringifyLocator));
7482
}
7583

0 commit comments

Comments
 (0)