mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-01 18:19:51 +00:00
9717259ffc
Enable no-else-return (with allowElseIf: false) and unicorn/no-lonely-if as errors in .oxlintrc.json and fix all 131 pre-existing violations (91 no-else-return, 40 unicorn/no-lonely-if) across 98 files. The no-else-return violations were fixed with the oxlint autofix (iterated to a fixpoint, plus two else-if chains that required --fix-dangerously) followed by Prettier formatting. One comment dropped by the autofix in lib/modules/manager/pub/artifacts.ts was restored manually. The unicorn/no-lonely-if violations were merged by hand, preserving comments and coverage-ignore hints. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
182 lines
5.0 KiB
TypeScript
182 lines
5.0 KiB
TypeScript
import { isString } from '@sindresorhus/is';
|
|
import { miscUtils, structUtils } from '@yarnpkg/core';
|
|
import { parseSyml } from '@yarnpkg/parsers';
|
|
import { logger } from '../../../../logger/index.ts';
|
|
import {
|
|
getSiblingFileName,
|
|
localPathExists,
|
|
readLocalFile,
|
|
} from '../../../../util/fs/index.ts';
|
|
import type { PackageFileContent } from '../../types.ts';
|
|
import type { YarnCatalogs } from '../schema.ts';
|
|
import type { NpmManagerData } from '../types.ts';
|
|
import { extractCatalogDeps } from './common/catalogs.ts';
|
|
import type { Catalog, LockFile } from './types.ts';
|
|
|
|
export async function getYarnLock(filePath: string): Promise<LockFile> {
|
|
// TODO #22198
|
|
const yarnLockRaw = (await readLocalFile(filePath, 'utf8'))!;
|
|
try {
|
|
const parsed = parseSyml(yarnLockRaw);
|
|
const lockedVersions: Record<string, string> = {};
|
|
let lockfileVersion: number | undefined;
|
|
|
|
for (const [key, val] of Object.entries(parsed)) {
|
|
if (key === '__metadata') {
|
|
// yarn 2
|
|
lockfileVersion = parseInt(val.cacheKey, 10);
|
|
logger.once.debug(
|
|
`yarn.lock ${filePath} has __metadata.cacheKey=${lockfileVersion}`,
|
|
);
|
|
} else {
|
|
for (const entry of key.split(', ')) {
|
|
try {
|
|
const { scope, name, range } = structUtils.parseDescriptor(entry);
|
|
const packageName = scope ? `@${scope}/${name}` : name;
|
|
const { selector } = structUtils.parseRange(range);
|
|
|
|
logger.trace({ entry, version: val.version });
|
|
lockedVersions[`${packageName}@${selector}`] = parsed[key].version;
|
|
} catch (err) {
|
|
logger.debug(
|
|
{ entry, err },
|
|
'Invalid descriptor or range found in yarn.lock',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const isYarn1 = !('__metadata' in parsed);
|
|
if (isYarn1) {
|
|
logger.once.debug(
|
|
`yarn.lock ${filePath} is has no __metadata so is yarn 1`,
|
|
);
|
|
} else {
|
|
logger.once.debug(
|
|
`yarn.lock ${filePath} is has __metadata so is yarn 2+`,
|
|
);
|
|
}
|
|
return {
|
|
isYarn1,
|
|
lockfileVersion,
|
|
lockedVersions,
|
|
};
|
|
} catch (err) {
|
|
logger.debug({ filePath, err }, 'Warning: Exception parsing yarn.lock');
|
|
return { isYarn1: true, lockedVersions: {} };
|
|
}
|
|
}
|
|
|
|
export function getZeroInstallPaths(yarnrcYml: string): string[] {
|
|
// TODO: fix type #22198
|
|
let conf: any;
|
|
try {
|
|
conf = parseSyml(yarnrcYml);
|
|
} catch (err) /* v8 ignore next -- TODO: add test #40625 */ {
|
|
logger.warn({ err }, 'Error parsing .yarnrc.yml');
|
|
}
|
|
const paths = [
|
|
conf?.cacheFolder ?? './.yarn/cache',
|
|
'.pnp.cjs',
|
|
'.pnp.js',
|
|
'.pnp.loader.mjs',
|
|
];
|
|
if (
|
|
conf &&
|
|
miscUtils.tryParseOptionalBoolean(conf.pnpEnableInlining) === false
|
|
) {
|
|
paths.push(conf.pnpDataPath ?? './.pnp.data.json');
|
|
}
|
|
return paths;
|
|
}
|
|
|
|
export async function isZeroInstall(yarnrcYmlPath: string): Promise<boolean> {
|
|
const yarnrcYml = await readLocalFile(yarnrcYmlPath, 'utf8');
|
|
// v8 ignore else -- TODO: add test #40625
|
|
if (isString(yarnrcYml)) {
|
|
const paths = getZeroInstallPaths(yarnrcYml);
|
|
for (const p of paths) {
|
|
if (await localPathExists(getSiblingFileName(yarnrcYmlPath, p))) {
|
|
logger.debug(`Detected Yarn zero-install in ${p}`);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export function getYarnVersionFromLock(lockfile: LockFile): string {
|
|
const { lockfileVersion, isYarn1 } = lockfile;
|
|
if (isYarn1) {
|
|
return '^1.22.18';
|
|
}
|
|
if (lockfileVersion && lockfileVersion >= 12) {
|
|
// This will probably be v5
|
|
return '>=4.0.0';
|
|
}
|
|
if (lockfileVersion && lockfileVersion >= 10) {
|
|
return '^4.0.0';
|
|
}
|
|
if (lockfileVersion && lockfileVersion >= 8) {
|
|
// https://github.com/yarnpkg/berry/commit/9bcd27ae34aee77a567dd104947407532fa179b3
|
|
return '^3.0.0';
|
|
}
|
|
if (lockfileVersion && lockfileVersion >= 6) {
|
|
// https://github.com/yarnpkg/berry/commit/f753790380cbda5b55d028ea84b199445129f9ba
|
|
return '^2.2.0';
|
|
}
|
|
|
|
return '^2.0.0';
|
|
}
|
|
|
|
export async function extractYarnCatalogs(
|
|
catalogs: YarnCatalogs,
|
|
packageFile: string,
|
|
hasPackageManager: boolean,
|
|
): Promise<PackageFileContent<NpmManagerData>> {
|
|
logger.trace(`yarn.extractYarnCatalogs(${packageFile})`);
|
|
|
|
const yarnCatalogs = yarnCatalogsToArray(catalogs);
|
|
|
|
const deps = extractCatalogDeps(yarnCatalogs, 'yarn');
|
|
|
|
let yarnLock: string | undefined;
|
|
const filePath = getSiblingFileName(packageFile, 'yarn.lock');
|
|
|
|
if (await localPathExists(filePath)) {
|
|
yarnLock = filePath;
|
|
}
|
|
|
|
return {
|
|
deps,
|
|
managerData: {
|
|
yarnLock,
|
|
hasPackageManager,
|
|
},
|
|
};
|
|
}
|
|
|
|
function yarnCatalogsToArray({
|
|
catalog: defaultCatalogDeps,
|
|
catalogs: namedCatalogs,
|
|
}: YarnCatalogs): Catalog[] {
|
|
const result: Catalog[] = [];
|
|
|
|
if (defaultCatalogDeps !== undefined) {
|
|
result.push({ name: 'default', dependencies: defaultCatalogDeps });
|
|
}
|
|
|
|
if (!namedCatalogs) {
|
|
return result;
|
|
}
|
|
|
|
for (const [name, dependencies] of Object.entries(namedCatalogs)) {
|
|
result.push({
|
|
name,
|
|
dependencies,
|
|
});
|
|
}
|
|
|
|
return result;
|
|
}
|