Skip to content

Commit

Permalink
Cherry-picks part of #4218
Browse files Browse the repository at this point in the history
  • Loading branch information
arcanis committed Aug 24, 2022
1 parent b400ff2 commit c601040
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 8 deletions.
54 changes: 48 additions & 6 deletions packages/plugin-patch/sources/commands/patchCommit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {BaseCommand, WorkspaceRequiredError} from '@yarnpkg/cli';
import {Configuration, Project, structUtils} from '@yarnpkg/core';
import {Configuration, Descriptor, DescriptorHash, Project, structUtils} from '@yarnpkg/core';
import {npath, xfs, ppath, PortablePath, Filename} from '@yarnpkg/fslib';
import {Command, Option, Usage, UsageError} from 'clipanion';

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

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

project.topLevelWorkspace.manifest.resolutions.push({
pattern: {descriptor: {fullName: structUtils.stringifyIdent(locator), description: meta.version}},
reference: `patch:${structUtils.stringifyLocator(locator)}#${relPath}`,
});
for (const pkg of project.storedPackages.values()) {
if (structUtils.isVirtualLocator(pkg))
continue;

const descriptor = pkg.dependencies.get(locator.identHash);
if (!descriptor)
continue;

const devirtualizedDescriptor = structUtils.isVirtualDescriptor(descriptor)
? structUtils.devirtualizeDescriptor(descriptor)
: descriptor;

const unpatchedDescriptor = patchUtils.ensureUnpatchedDescriptor(devirtualizedDescriptor);

const resolution = project.storedResolutions.get(unpatchedDescriptor.descriptorHash);
if (!resolution)
throw new Error(`Assertion failed: Expected the resolution to have been registered`);

const dependency = project.storedPackages.get(resolution);
if (!dependency)
throw new Error(`Assertion failed: Expected the package to have been registered`);

const originalPkg = project.originalPackages.get(pkg.locatorHash);
if (!originalPkg)
throw new Error(`Assertion failed: Expected the original package to have been registered`);

const originalDependency = originalPkg.dependencies.get(descriptor.identHash);
if (!originalDependency)
throw new Error(`Assertion failed: Expected the original dependency to have been registered`);

transitiveDependencies.set(originalDependency.descriptorHash, originalDependency);
}

for (const originalDescriptor of transitiveDependencies.values()) {
const newDescriptor = patchUtils.makeDescriptor(originalDescriptor, {
parentLocator: null,
sourceDescriptor: structUtils.convertLocatorToDescriptor(locator),
sourceVersion: null,
patchPaths: [`./${ppath.relative(project.cwd, patchPath)}` as PortablePath],
});

project.topLevelWorkspace.manifest.resolutions.push({
pattern: {descriptor: {fullName: structUtils.stringifyIdent(newDescriptor), description: originalDescriptor.range}},
reference: newDescriptor.range,
});
}

await project.persist();
}
Expand Down
12 changes: 10 additions & 2 deletions packages/plugin-patch/sources/patchUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ export function parseLocator(locator: Locator) {
return {...rest, sourceLocator: sourceItem};
}

export function ensureUnpatchedDescriptor(descriptor: Descriptor) {
if (!descriptor.range.startsWith(`patch:`))
return descriptor;

const {sourceItem} = parseSpec(descriptor.range, structUtils.parseDescriptor);
return sourceItem;
}

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) {
const parentLocatorSpread = parentLocator !== null
? {locator: structUtils.stringifyLocator(parentLocator)}
Expand All @@ -66,10 +74,10 @@ function makeSpec<T>({parentLocator, sourceItem, patchPaths, sourceVersion, patc
}

export function makeDescriptor(ident: Ident, {parentLocator, sourceDescriptor, patchPaths}: ReturnType<typeof parseDescriptor>) {
return structUtils.makeLocator(ident, makeSpec({parentLocator, sourceItem: sourceDescriptor, patchPaths}, structUtils.stringifyDescriptor));
return structUtils.makeDescriptor(ident, makeSpec({parentLocator, sourceItem: sourceDescriptor, patchPaths}, structUtils.stringifyDescriptor));
}

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

Expand Down

0 comments on commit c601040

Please sign in to comment.