mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-27 15:58:48 +00:00
03baf6ee4a
* test(noNewURL): add new rule enforcing parseUrl() from 'lib/util/url.ts' * replace newURL with parseUrl * remove non-null assertions marks if appropiate * test: add additional tests * test: add additional tests and ignore where it makes sense * implement suggestions * test: further improve coverage * apply suggestion
185 lines
6.0 KiB
TypeScript
185 lines
6.0 KiB
TypeScript
import { logger } from '../../../logger/index.ts';
|
|
import type { Http, HttpOptions } from '../../../util/http/index.ts';
|
|
import { joinUrlParts, parseUrl } from '../../../util/url.ts';
|
|
|
|
/**
|
|
* Extracts the base suite URL from a package URL by removing the last two path segments.
|
|
*
|
|
* @param basePackageUrl - The base URL of the package.
|
|
* @returns The base suite URL.
|
|
*
|
|
* @example
|
|
* // Returns 'https://deb.debian.org/debian/dists/bullseye'
|
|
* getBaseReleaseUrl('https://deb.debian.org/debian/dists/bullseye/main/binary-amd64');
|
|
*/
|
|
export function getBaseSuiteUrl(basePackageUrl: string): string {
|
|
const urlParts = basePackageUrl.split('/');
|
|
return urlParts.slice(0, urlParts.length - 2).join('/');
|
|
}
|
|
|
|
/**
|
|
* Constructs the component URLs from the given registry URL.
|
|
*
|
|
* @param registryUrl - The base URL of the registry.
|
|
* @returns An array of component URLs.
|
|
* @throws Will throw an error if required parameters are missing from the URL.
|
|
*/
|
|
export function constructComponentUrls(registryUrl: string): string[] {
|
|
const REQUIRED_PARAMS = ['components', 'binaryArch'];
|
|
const OPTIONAL_PARAMS = ['suite', 'release'];
|
|
|
|
try {
|
|
const url = parseUrl(registryUrl);
|
|
if (!url) {
|
|
return [];
|
|
}
|
|
validateUrlAndParams(url, REQUIRED_PARAMS);
|
|
|
|
const suite = getReleaseParam(url, OPTIONAL_PARAMS);
|
|
const binaryArch = url.searchParams.get('binaryArch');
|
|
const components = url.searchParams.get('components')!.split(',');
|
|
|
|
// Clean up URL search parameters for constructing new URLs
|
|
[...REQUIRED_PARAMS, ...OPTIONAL_PARAMS].forEach((param) =>
|
|
url.searchParams.delete(param),
|
|
);
|
|
|
|
return components.map((component) =>
|
|
joinUrlParts(
|
|
url.toString(),
|
|
`dists`,
|
|
suite,
|
|
component,
|
|
`binary-${binaryArch}`,
|
|
),
|
|
);
|
|
} catch (error) {
|
|
throw new Error(
|
|
`Invalid deb repo URL: ${registryUrl} - see documentation: ${error.message}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validates that the required parameters are present in the URL.
|
|
*
|
|
* @param url - The URL to validate.
|
|
* @param requiredParams - The list of required query parameters.
|
|
* @throws Will throw an error if a required parameter is missing.
|
|
*/
|
|
function validateUrlAndParams(url: URL, requiredParams: string[]): void {
|
|
for (const param of requiredParams) {
|
|
if (!url.searchParams.has(param)) {
|
|
throw new Error(`Missing required query parameter '${param}'`);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieves the suite parameter from the URL.
|
|
*
|
|
* @param url - The URL to retrieve the suite parameter from.
|
|
* @param optionalParams - The list of optional query parameters.
|
|
* @returns The value of the suite parameter.
|
|
* @throws Will throw an error if none of the optional parameters are found.
|
|
*/
|
|
function getReleaseParam(url: URL, optionalParams: string[]): string {
|
|
for (const param of optionalParams) {
|
|
const paramValue = url.searchParams.get(param);
|
|
if (paramValue !== null) {
|
|
if (param === 'release') {
|
|
logger.debug(
|
|
'Deprecation notice. Use `suite` instead of `release` for deb repo URLs',
|
|
);
|
|
}
|
|
return paramValue;
|
|
}
|
|
}
|
|
throw new Error(`Missing one of suite query parameter`);
|
|
}
|
|
|
|
/**
|
|
* Checks if a packageUrl content has been modified since the specified timestamp.
|
|
*
|
|
* @param packageUrl - The URL to check.
|
|
* @param lastDownloadTimestamp - The timestamp of the last download.
|
|
* @returns True if the content has been modified, otherwise false.
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since
|
|
*/
|
|
export async function checkIfModified(
|
|
packageUrl: string,
|
|
lastDownloadTimestamp: Date,
|
|
http: Http,
|
|
): Promise<boolean> {
|
|
const options: HttpOptions = {
|
|
headers: {
|
|
'If-Modified-Since': lastDownloadTimestamp.toUTCString(),
|
|
},
|
|
};
|
|
|
|
try {
|
|
const response = await http.head(packageUrl, options);
|
|
return response.statusCode !== 304;
|
|
} catch (error) {
|
|
logger.warn(
|
|
{ packageUrl, lastDownloadTimestamp, errorMessage: error.message },
|
|
'Could not determine if package file is modified since last download',
|
|
);
|
|
return true; // Assume it needs to be downloaded if check fails
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a URL for accessing the component directory for a specific release and architecture.
|
|
*
|
|
* @param baseUrl - The base URL of the repository.
|
|
* @param release - The release name or codename (e.g., 'buster', 'bullseye').
|
|
* @param component - The component name (e.g., 'main', 'contrib', 'non-free').
|
|
* @param arch - The architecture name (e.g., 'amd64', 'i386').
|
|
* @returns The complete URL to the component directory.
|
|
*/
|
|
export function getComponentUrl(
|
|
baseUrl: string,
|
|
release: string,
|
|
component: string,
|
|
arch: string,
|
|
): string {
|
|
return `${baseUrl}/debian/dists/${release}/${component}/binary-${arch}`;
|
|
}
|
|
|
|
/**
|
|
* Constructs a URL for accessing the Packages.gz file for a specific component, release, and architecture.
|
|
*
|
|
* @param baseUrl - The base URL of the repository.
|
|
* @param release - The release name or codename (e.g., 'buster', 'bullseye').
|
|
* @param component - The component name (e.g., 'main', 'contrib', 'non-free').
|
|
* @param arch - The architecture name (e.g., 'amd64', 'i386').
|
|
* @returns The complete URL to the Packages.gz file.
|
|
*/
|
|
export function getPackageUrl(
|
|
baseUrl: string,
|
|
release: string,
|
|
component: string,
|
|
arch: string,
|
|
): string {
|
|
return `${getComponentUrl(baseUrl, release, component, arch)}/Packages.gz`;
|
|
}
|
|
|
|
/**
|
|
* Constructs a URL used generating the component url with specific release, components, and architecture.
|
|
*
|
|
* @param baseUrl - The base URL of the repository.
|
|
* @param release - The release name or codename (e.g., 'buster', 'bullseye').
|
|
* @param components - An array of component names (e.g., ['main', 'contrib', 'non-free']).
|
|
* @param arch - The architecture name (e.g., 'amd64', 'i386').
|
|
* @returns The complete URL to the package registry.
|
|
*/
|
|
export function getRegistryUrl(
|
|
baseUrl: string,
|
|
release: string,
|
|
components: string[],
|
|
arch: string,
|
|
): string {
|
|
return `${baseUrl}/debian?suite=${release}&components=${components.join(',')}&binaryArch=${arch}`;
|
|
}
|