diff --git a/.yarn/versions/70b508e3.yml b/.yarn/versions/70b508e3.yml new file mode 100644 index 000000000000..c36e978ccb8a --- /dev/null +++ b/.yarn/versions/70b508e3.yml @@ -0,0 +1,24 @@ +releases: + "@yarnpkg/cli": patch + "@yarnpkg/plugin-http": patch + +declined: + - "@yarnpkg/plugin-compat" + - "@yarnpkg/plugin-constraints" + - "@yarnpkg/plugin-dlx" + - "@yarnpkg/plugin-essentials" + - "@yarnpkg/plugin-init" + - "@yarnpkg/plugin-interactive-tools" + - "@yarnpkg/plugin-nm" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-pnp" + - "@yarnpkg/plugin-pnpm" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/plugin-workspace-tools" + - "@yarnpkg/builder" + - "@yarnpkg/core" + - "@yarnpkg/doctor" diff --git a/packages/plugin-http/sources/TarballHttpFetcher.ts b/packages/plugin-http/sources/TarballHttpFetcher.ts index cf39c8c136d2..3168a14fe74b 100644 --- a/packages/plugin-http/sources/TarballHttpFetcher.ts +++ b/packages/plugin-http/sources/TarballHttpFetcher.ts @@ -2,17 +2,11 @@ import {Fetcher, FetchOptions, MinimalFetchOptions} from '@yarnpkg/core'; import {Locator} from '@yarnpkg/core'; import {httpUtils, structUtils, tgzUtils} from '@yarnpkg/core'; -import {TARBALL_REGEXP, PROTOCOL_REGEXP} from './constants'; +import * as urlUtils from './urlUtils'; export class TarballHttpFetcher implements Fetcher { supports(locator: Locator, opts: MinimalFetchOptions) { - if (!TARBALL_REGEXP.test(locator.reference)) - return false; - - if (PROTOCOL_REGEXP.test(locator.reference)) - return true; - - return false; + return urlUtils.isTgzUrl(locator.reference); } getLocalPath(locator: Locator, opts: FetchOptions) { diff --git a/packages/plugin-http/sources/TarballHttpResolver.ts b/packages/plugin-http/sources/TarballHttpResolver.ts index 5d46d07fd4d7..28d856b79f07 100644 --- a/packages/plugin-http/sources/TarballHttpResolver.ts +++ b/packages/plugin-http/sources/TarballHttpResolver.ts @@ -3,27 +3,15 @@ import {Descriptor, Locator, Manifest} from '@yarnpkg import {LinkType} from '@yarnpkg/core'; import {miscUtils, structUtils} from '@yarnpkg/core'; -import {PROTOCOL_REGEXP, TARBALL_REGEXP} from './constants'; +import * as urlUtils from './urlUtils'; export class TarballHttpResolver implements Resolver { supportsDescriptor(descriptor: Descriptor, opts: MinimalResolveOptions) { - if (!TARBALL_REGEXP.test(descriptor.range)) - return false; - - if (PROTOCOL_REGEXP.test(descriptor.range)) - return true; - - return false; + return urlUtils.isTgzUrl(descriptor.range); } supportsLocator(locator: Locator, opts: MinimalResolveOptions) { - if (!TARBALL_REGEXP.test(locator.reference)) - return false; - - if (PROTOCOL_REGEXP.test(locator.reference)) - return true; - - return false; + return urlUtils.isTgzUrl(locator.reference); } shouldPersistResolution(locator: Locator, opts: MinimalResolveOptions) { diff --git a/packages/plugin-http/sources/constants.ts b/packages/plugin-http/sources/constants.ts deleted file mode 100644 index 80edec433111..000000000000 --- a/packages/plugin-http/sources/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const TARBALL_REGEXP = /^[^?]*\.(?:tar\.gz|tgz)(?:\?.*)?(?:#.*)?$/; - -export const PROTOCOL_REGEXP = /^https?:/; diff --git a/packages/plugin-http/sources/urlUtils.ts b/packages/plugin-http/sources/urlUtils.ts new file mode 100644 index 000000000000..df6d1c791c29 --- /dev/null +++ b/packages/plugin-http/sources/urlUtils.ts @@ -0,0 +1,16 @@ +export function isTgzUrl(url: string) { + let parsed: URL; + try { + parsed = new URL(url); + } catch { + return false; + } + + if (parsed.protocol !== `http:` && parsed.protocol !== `https:`) + return false; + + if (!parsed.pathname.match(/(\.tar\.gz|\.tgz|\/[^.]+)$/)) + return false; + + return true; +} diff --git a/packages/plugin-http/tests/urlUtils.test.ts b/packages/plugin-http/tests/urlUtils.test.ts new file mode 100644 index 000000000000..71f2a6e27308 --- /dev/null +++ b/packages/plugin-http/tests/urlUtils.test.ts @@ -0,0 +1,17 @@ +import * as urlUtils from '../sources/urlUtils'; + +const EXPECTATIONS: Array<[string, boolean]> = [ + [`https://example.org/package.tar.gz`, true], + [`https://example.org/package.tgz`, true], + [`https://example.org/package`, true], + [`https://example.org/package.git`, false], + [`https://example.org/package.tgz.git`, false], + [`ftp://example.org/package.tgz`, false], + [`1.2.3`, false], +]; + +for (const [url, expected] of EXPECTATIONS) { + test(`isTgzUrl(${JSON.stringify(url)}) === ${JSON.stringify(expected)}`, () => { + expect(urlUtils.isTgzUrl(url)).toEqual(expected); + }); +}