mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-13 15:36:25 +00:00
fix(packagist): Replace V2 URL path instead of joining it (#20709)
This commit is contained in:
parent
c5edc5d54e
commit
cd06651f89
3 changed files with 110 additions and 53 deletions
|
@ -5,7 +5,7 @@ import { cache } from '../../../util/cache/package/decorator';
|
||||||
import * as hostRules from '../../../util/host-rules';
|
import * as hostRules from '../../../util/host-rules';
|
||||||
import type { HttpOptions } from '../../../util/http/types';
|
import type { HttpOptions } from '../../../util/http/types';
|
||||||
import * as p from '../../../util/promises';
|
import * as p from '../../../util/promises';
|
||||||
import { parseUrl, resolveBaseUrl } from '../../../util/url';
|
import { replaceUrlPath, resolveBaseUrl } from '../../../util/url';
|
||||||
import * as composerVersioning from '../../versioning/composer';
|
import * as composerVersioning from '../../versioning/composer';
|
||||||
import { Datasource } from '../datasource';
|
import { Datasource } from '../datasource';
|
||||||
import type { GetReleasesConfig, ReleaseResult } from '../types';
|
import type { GetReleasesConfig, ReleaseResult } from '../types';
|
||||||
|
@ -70,7 +70,7 @@ export class PackagistDatasource extends Datasource {
|
||||||
): string {
|
): string {
|
||||||
const { key, hash } = regFile;
|
const { key, hash } = regFile;
|
||||||
const fileName = hash ? key.replace('%hash%', hash) : key;
|
const fileName = hash ? key.replace('%hash%', hash) : key;
|
||||||
const url = `${regUrl}/${fileName}`;
|
const url = resolveBaseUrl(regUrl, fileName);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,12 +124,16 @@ export class PackagistDatasource extends Datasource {
|
||||||
metadataUrl: string,
|
metadataUrl: string,
|
||||||
packageName: string
|
packageName: string
|
||||||
): Promise<ReleaseResult | null> {
|
): Promise<ReleaseResult | null> {
|
||||||
let pkgUrl = metadataUrl.replace('%package%', packageName);
|
const pkgUrl = replaceUrlPath(
|
||||||
pkgUrl = parseUrl(pkgUrl) ? pkgUrl : resolveBaseUrl(registryUrl, pkgUrl);
|
registryUrl,
|
||||||
|
metadataUrl.replace('%package%', packageName)
|
||||||
|
);
|
||||||
const pkgPromise = this.getJson(pkgUrl, z.unknown());
|
const pkgPromise = this.getJson(pkgUrl, z.unknown());
|
||||||
|
|
||||||
let devUrl = metadataUrl.replace('%package%', `${packageName}~dev`);
|
const devUrl = replaceUrlPath(
|
||||||
devUrl = parseUrl(devUrl) ? devUrl : resolveBaseUrl(registryUrl, devUrl);
|
registryUrl,
|
||||||
|
metadataUrl.replace('%package%', `${packageName}~dev`)
|
||||||
|
);
|
||||||
const devPromise = this.getJson(devUrl, z.unknown()).then(
|
const devPromise = this.getJson(devUrl, z.unknown()).then(
|
||||||
(x) => x,
|
(x) => x,
|
||||||
() => null
|
() => null
|
||||||
|
@ -144,8 +148,6 @@ export class PackagistDatasource extends Datasource {
|
||||||
registryUrl: string,
|
registryUrl: string,
|
||||||
registryMeta: RegistryMeta
|
registryMeta: RegistryMeta
|
||||||
): string | null {
|
): string | null {
|
||||||
const { origin: registryHost } = new URL(registryUrl);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
registryMeta.providersUrl &&
|
registryMeta.providersUrl &&
|
||||||
packageName in registryMeta.providerPackages
|
packageName in registryMeta.providerPackages
|
||||||
|
@ -155,12 +157,12 @@ export class PackagistDatasource extends Datasource {
|
||||||
if (hash) {
|
if (hash) {
|
||||||
url = url.replace('%hash%', hash);
|
url = url.replace('%hash%', hash);
|
||||||
}
|
}
|
||||||
return resolveBaseUrl(registryHost, url);
|
return replaceUrlPath(registryUrl, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registryMeta.providersLazyUrl) {
|
if (registryMeta.providersLazyUrl) {
|
||||||
return resolveBaseUrl(
|
return replaceUrlPath(
|
||||||
registryHost,
|
registryUrl,
|
||||||
registryMeta.providersLazyUrl.replace('%package%', packageName)
|
registryMeta.providersLazyUrl.replace('%package%', packageName)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,57 +6,91 @@ import {
|
||||||
joinUrlParts,
|
joinUrlParts,
|
||||||
parseLinkHeader,
|
parseLinkHeader,
|
||||||
parseUrl,
|
parseUrl,
|
||||||
|
replaceUrlPath,
|
||||||
resolveBaseUrl,
|
resolveBaseUrl,
|
||||||
trimTrailingSlash,
|
trimTrailingSlash,
|
||||||
validateUrl,
|
validateUrl,
|
||||||
} from './url';
|
} from './url';
|
||||||
|
|
||||||
describe('util/url', () => {
|
describe('util/url', () => {
|
||||||
test.each([
|
test.each`
|
||||||
['http://foo.io', '', 'http://foo.io'],
|
baseUrl | x | result
|
||||||
['http://foo.io/', '', 'http://foo.io'],
|
${'http://foo.io'} | ${''} | ${'http://foo.io'}
|
||||||
['http://foo.io', '/', 'http://foo.io/'],
|
${'http://foo.io/'} | ${''} | ${'http://foo.io'}
|
||||||
['http://foo.io/', '/', 'http://foo.io/'],
|
${'http://foo.io'} | ${'/'} | ${'http://foo.io/'}
|
||||||
|
${'http://foo.io/'} | ${'/'} | ${'http://foo.io/'}
|
||||||
['http://foo.io', '/aaa', 'http://foo.io/aaa'],
|
${'http://foo.io'} | ${'/aaa'} | ${'http://foo.io/aaa'}
|
||||||
['http://foo.io', 'aaa', 'http://foo.io/aaa'],
|
${'http://foo.io'} | ${'aaa'} | ${'http://foo.io/aaa'}
|
||||||
['http://foo.io/', '/aaa', 'http://foo.io/aaa'],
|
${'http://foo.io/'} | ${'/aaa'} | ${'http://foo.io/aaa'}
|
||||||
['http://foo.io/', 'aaa', 'http://foo.io/aaa'],
|
${'http://foo.io/'} | ${'aaa'} | ${'http://foo.io/aaa'}
|
||||||
['http://foo.io', '/aaa/', 'http://foo.io/aaa/'],
|
${'http://foo.io'} | ${'/aaa/'} | ${'http://foo.io/aaa/'}
|
||||||
['http://foo.io', 'aaa/', 'http://foo.io/aaa/'],
|
${'http://foo.io'} | ${'aaa/'} | ${'http://foo.io/aaa/'}
|
||||||
['http://foo.io/', '/aaa/', 'http://foo.io/aaa/'],
|
${'http://foo.io/'} | ${'/aaa/'} | ${'http://foo.io/aaa/'}
|
||||||
['http://foo.io/', 'aaa/', 'http://foo.io/aaa/'],
|
${'http://foo.io/'} | ${'aaa/'} | ${'http://foo.io/aaa/'}
|
||||||
|
${'http://foo.io/aaa'} | ${'/bbb'} | ${'http://foo.io/aaa/bbb'}
|
||||||
['http://foo.io/aaa', '/bbb', 'http://foo.io/aaa/bbb'],
|
${'http://foo.io/aaa'} | ${'bbb'} | ${'http://foo.io/aaa/bbb'}
|
||||||
['http://foo.io/aaa', 'bbb', 'http://foo.io/aaa/bbb'],
|
${'http://foo.io/aaa/'} | ${'/bbb'} | ${'http://foo.io/aaa/bbb'}
|
||||||
['http://foo.io/aaa/', '/bbb', 'http://foo.io/aaa/bbb'],
|
${'http://foo.io/aaa/'} | ${'bbb'} | ${'http://foo.io/aaa/bbb'}
|
||||||
['http://foo.io/aaa/', 'bbb', 'http://foo.io/aaa/bbb'],
|
${'http://foo.io/aaa'} | ${'/bbb/'} | ${'http://foo.io/aaa/bbb/'}
|
||||||
|
${'http://foo.io/aaa'} | ${'bbb/'} | ${'http://foo.io/aaa/bbb/'}
|
||||||
['http://foo.io/aaa', '/bbb/', 'http://foo.io/aaa/bbb/'],
|
${'http://foo.io/aaa/'} | ${'/bbb/'} | ${'http://foo.io/aaa/bbb/'}
|
||||||
['http://foo.io/aaa', 'bbb/', 'http://foo.io/aaa/bbb/'],
|
${'http://foo.io/aaa/'} | ${'bbb/'} | ${'http://foo.io/aaa/bbb/'}
|
||||||
['http://foo.io/aaa/', '/bbb/', 'http://foo.io/aaa/bbb/'],
|
${'http://foo.io'} | ${'http://bar.io/bbb'} | ${'http://bar.io/bbb'}
|
||||||
['http://foo.io/aaa/', 'bbb/', 'http://foo.io/aaa/bbb/'],
|
${'http://foo.io/'} | ${'http://bar.io/bbb'} | ${'http://bar.io/bbb'}
|
||||||
|
${'http://foo.io/aaa'} | ${'http://bar.io/bbb'} | ${'http://bar.io/bbb'}
|
||||||
['http://foo.io', 'http://bar.io/bbb', 'http://bar.io/bbb'],
|
${'http://foo.io/aaa/'} | ${'http://bar.io/bbb'} | ${'http://bar.io/bbb'}
|
||||||
['http://foo.io/', 'http://bar.io/bbb', 'http://bar.io/bbb'],
|
${'http://foo.io'} | ${'http://bar.io/bbb/'} | ${'http://bar.io/bbb/'}
|
||||||
['http://foo.io/aaa', 'http://bar.io/bbb', 'http://bar.io/bbb'],
|
${'http://foo.io/'} | ${'http://bar.io/bbb/'} | ${'http://bar.io/bbb/'}
|
||||||
['http://foo.io/aaa/', 'http://bar.io/bbb', 'http://bar.io/bbb'],
|
${'http://foo.io/aaa'} | ${'http://bar.io/bbb/'} | ${'http://bar.io/bbb/'}
|
||||||
|
${'http://foo.io/aaa/'} | ${'http://bar.io/bbb/'} | ${'http://bar.io/bbb/'}
|
||||||
['http://foo.io', 'http://bar.io/bbb/', 'http://bar.io/bbb/'],
|
${'http://foo.io'} | ${'aaa?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
['http://foo.io/', 'http://bar.io/bbb/', 'http://bar.io/bbb/'],
|
${'http://foo.io'} | ${'/aaa?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
['http://foo.io/aaa', 'http://bar.io/bbb/', 'http://bar.io/bbb/'],
|
${'http://foo.io/'} | ${'aaa?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
['http://foo.io/aaa/', 'http://bar.io/bbb/', 'http://bar.io/bbb/'],
|
${'http://foo.io/'} | ${'/aaa?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
|
${'http://foo.io'} | ${'aaa/?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
['http://foo.io', 'aaa?bbb=z', 'http://foo.io/aaa?bbb=z'],
|
`('$baseUrl + $x => $result', ({ baseUrl, x, result }) => {
|
||||||
['http://foo.io', '/aaa?bbb=z', 'http://foo.io/aaa?bbb=z'],
|
|
||||||
['http://foo.io/', 'aaa?bbb=z', 'http://foo.io/aaa?bbb=z'],
|
|
||||||
['http://foo.io/', '/aaa?bbb=z', 'http://foo.io/aaa?bbb=z'],
|
|
||||||
|
|
||||||
['http://foo.io', 'aaa/?bbb=z', 'http://foo.io/aaa?bbb=z'],
|
|
||||||
])('%s + %s => %s', (baseUrl, x, result) => {
|
|
||||||
expect(resolveBaseUrl(baseUrl, x)).toBe(result);
|
expect(resolveBaseUrl(baseUrl, x)).toBe(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.each`
|
||||||
|
baseUrl | x | result
|
||||||
|
${'http://foo.io'} | ${''} | ${'http://foo.io'}
|
||||||
|
${'http://foo.io/'} | ${''} | ${'http://foo.io'}
|
||||||
|
${'http://foo.io'} | ${'/'} | ${'http://foo.io/'}
|
||||||
|
${'http://foo.io/'} | ${'/'} | ${'http://foo.io/'}
|
||||||
|
${'http://foo.io'} | ${'/aaa'} | ${'http://foo.io/aaa'}
|
||||||
|
${'http://foo.io'} | ${'aaa'} | ${'http://foo.io/aaa'}
|
||||||
|
${'http://foo.io/'} | ${'/aaa'} | ${'http://foo.io/aaa'}
|
||||||
|
${'http://foo.io/'} | ${'aaa'} | ${'http://foo.io/aaa'}
|
||||||
|
${'http://foo.io'} | ${'/aaa/'} | ${'http://foo.io/aaa/'}
|
||||||
|
${'http://foo.io'} | ${'aaa/'} | ${'http://foo.io/aaa/'}
|
||||||
|
${'http://foo.io/'} | ${'/aaa/'} | ${'http://foo.io/aaa/'}
|
||||||
|
${'http://foo.io/'} | ${'aaa/'} | ${'http://foo.io/aaa/'}
|
||||||
|
${'http://foo.io/aaa'} | ${'/bbb'} | ${'http://foo.io/bbb'}
|
||||||
|
${'http://foo.io/aaa'} | ${'bbb'} | ${'http://foo.io/bbb'}
|
||||||
|
${'http://foo.io/aaa/'} | ${'/bbb'} | ${'http://foo.io/bbb'}
|
||||||
|
${'http://foo.io/aaa/'} | ${'bbb'} | ${'http://foo.io/bbb'}
|
||||||
|
${'http://foo.io/aaa'} | ${'/bbb/'} | ${'http://foo.io/bbb/'}
|
||||||
|
${'http://foo.io/aaa'} | ${'bbb/'} | ${'http://foo.io/bbb/'}
|
||||||
|
${'http://foo.io/aaa/'} | ${'/bbb/'} | ${'http://foo.io/bbb/'}
|
||||||
|
${'http://foo.io/aaa/'} | ${'bbb/'} | ${'http://foo.io/bbb/'}
|
||||||
|
${'http://foo.io'} | ${'http://bar.io/bbb'} | ${'http://bar.io/bbb'}
|
||||||
|
${'http://foo.io/'} | ${'http://bar.io/bbb'} | ${'http://bar.io/bbb'}
|
||||||
|
${'http://foo.io/aaa'} | ${'http://bar.io/bbb'} | ${'http://bar.io/bbb'}
|
||||||
|
${'http://foo.io/aaa/'} | ${'http://bar.io/bbb'} | ${'http://bar.io/bbb'}
|
||||||
|
${'http://foo.io'} | ${'http://bar.io/bbb/'} | ${'http://bar.io/bbb/'}
|
||||||
|
${'http://foo.io/'} | ${'http://bar.io/bbb/'} | ${'http://bar.io/bbb/'}
|
||||||
|
${'http://foo.io/aaa'} | ${'http://bar.io/bbb/'} | ${'http://bar.io/bbb/'}
|
||||||
|
${'http://foo.io/aaa/'} | ${'http://bar.io/bbb/'} | ${'http://bar.io/bbb/'}
|
||||||
|
${'http://foo.io'} | ${'aaa?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
|
${'http://foo.io'} | ${'/aaa?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
|
${'http://foo.io/'} | ${'aaa?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
|
${'http://foo.io/'} | ${'/aaa?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
|
${'http://foo.io'} | ${'aaa/?bbb=z'} | ${'http://foo.io/aaa?bbb=z'}
|
||||||
|
`('replaceUrlPath("$baseUrl", "$x") => $result', ({ baseUrl, x, result }) => {
|
||||||
|
expect(replaceUrlPath(baseUrl, x)).toBe(result);
|
||||||
|
});
|
||||||
|
|
||||||
it('getQueryString', () => {
|
it('getQueryString', () => {
|
||||||
expect(getQueryString({ a: 1, b: [1, 2] })).toBe('a=1&b=1&b=2');
|
expect(getQueryString({ a: 1, b: [1, 2] })).toBe('a=1&b=1&b=2');
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,6 +30,12 @@ export function trimLeadingSlash(path: string): string {
|
||||||
return path.replace(/^\/+/, '');
|
return path.replace(/^\/+/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves an input path against a base URL
|
||||||
|
*
|
||||||
|
* @param baseUrl - base URL to resolve against
|
||||||
|
* @param input - input path (if this is a full URL, it will be returned)
|
||||||
|
*/
|
||||||
export function resolveBaseUrl(baseUrl: string, input: string | URL): string {
|
export function resolveBaseUrl(baseUrl: string, input: string | URL): string {
|
||||||
const inputString = input.toString();
|
const inputString = input.toString();
|
||||||
|
|
||||||
|
@ -44,6 +50,21 @@ export function resolveBaseUrl(baseUrl: string, input: string | URL): string {
|
||||||
return host ? inputString : urlJoin(baseUrl, pathname || '');
|
return host ? inputString : urlJoin(baseUrl, pathname || '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the path of a URL with a new path
|
||||||
|
*
|
||||||
|
* @param baseUrl - source URL
|
||||||
|
* @param path - replacement path (if this is a full URL, it will be returned)
|
||||||
|
*/
|
||||||
|
export function replaceUrlPath(baseUrl: string | URL, path: string): string {
|
||||||
|
if (parseUrl(path)) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { origin } = is.string(baseUrl) ? new URL(baseUrl) : baseUrl;
|
||||||
|
return urlJoin(origin, path);
|
||||||
|
}
|
||||||
|
|
||||||
export function getQueryString(params: Record<string, any>): string {
|
export function getQueryString(params: Record<string, any>): string {
|
||||||
const usp = new URLSearchParams();
|
const usp = new URLSearchParams();
|
||||||
for (const [k, v] of Object.entries(params)) {
|
for (const [k, v] of Object.entries(params)) {
|
||||||
|
|
Loading…
Reference in a new issue