diff --git a/packages/zpm/src/fetchers/patch.rs b/packages/zpm/src/fetchers/patch.rs index 187411d7..5324f420 100644 --- a/packages/zpm/src/fetchers/patch.rs +++ b/packages/zpm/src/fetchers/patch.rs @@ -20,6 +20,15 @@ pub fn has_builtin_patch(ident: &Ident) -> bool { .any(|(name, _)| *name == ident.as_str()) } +fn patch_file_path(path: &str) -> &str { + // Yarn patch references may include metadata suffixes like: + // "::version=1.2.3&hash=abcdef". Only the filesystem path + // before "::" points to the actual patch file on disk. + path.split_once("::") + .map(|(file_path, _)| file_path) + .unwrap_or(path) +} + pub async fn fetch_locator<'a>(context: &InstallContext<'a>, locator: &Locator, params: &PatchReference, is_mock_request: bool, dependencies: Vec) -> Result { let package_cache = context.package_cache .expect("The package cache is required to fetch a patch package"); @@ -45,7 +54,9 @@ pub async fn fetch_locator<'a>(context: &InstallContext<'a>, locator: &Locator, let mut is_builtin = false; - let patch_content = match params.path.as_str() { + let file_path = patch_file_path(¶ms.path); + + let patch_content = match file_path { "" => { let compressed_patch = BUILTIN_PATCHES.iter() .find(|(name, _)| name == &locator.ident.as_str()) diff --git a/tests/acceptance-tests/pkg-tests-specs/sources/protocols/patch.test.ts b/tests/acceptance-tests/pkg-tests-specs/sources/protocols/patch.test.ts index 23ad98da..ac1883cd 100644 --- a/tests/acceptance-tests/pkg-tests-specs/sources/protocols/patch.test.ts +++ b/tests/acceptance-tests/pkg-tests-specs/sources/protocols/patch.test.ts @@ -191,6 +191,26 @@ describe(`Protocols`, () => { ), ); + test( + `it should support patch paths containing metadata suffixes`, + makeTemporaryEnv( + { + dependencies: {[`no-deps`]: `patch:no-deps@1.0.0#${PATCH_NAME}::version=1.0.0&hash=deadbeef`}, + }, + async ({path, run, source}) => { + await xfs.writeFilePromise(ppath.join(path, PATCH_NAME), NO_DEPS_PATCH); + + await run(`install`); + + await expect(source(`require('no-deps')`)).resolves.toMatchObject({ + name: `no-deps`, + version: `1.0.0`, + hello: `world`, + }); + }, + ), + ); + test( `it should support applying a patch on a patch`, makeTemporaryEnv(