Files
renovate/lib/modules/manager/conan/extract.ts
Sergei Zharinov 930cf6633c refactor: Rewrite imports with .ts extensions (#40700)
fix: Additional vi.mock path corrections and prettier formatting
2026-01-26 22:48:17 +00:00

84 lines
3.0 KiB
TypeScript

import { isNonEmptyString } from '@sindresorhus/is';
import { regEx } from '../../../util/regex.ts';
import type { PackageDependency, PackageFileContent } from '../types.ts';
import { isComment } from './common.ts';
const regex = regEx(
`(?:^|["'])(?<name>[-\\w]+)/(?<version>[^@#\n{*"']+)(?<userChannel>@[-\\w]+(?:/[^#\n.{*"' ]+|))?#?(?<revision>[-_a-f0-9]+[^\n{*"'])?`,
);
function setDepType(content: string, originalType: string): string {
let depType = originalType;
if (content.includes('python_requires')) {
depType = 'python_requires';
} else if (content.includes('build_require')) {
depType = 'build_requires';
} else if (content.includes('requires')) {
depType = 'requires';
}
return depType;
}
export function extractPackageFile(content: string): PackageFileContent | null {
// only process sections where requirements are defined
const sections = content.split(regEx(/def |\n\[/)).filter(
(part) =>
part.includes('python_requires') || // only matches python_requires
part.includes('build_require') || // matches [build_requires], build_requirements(), and build_requires
part.includes('require'), // matches [requires], requirements(), and requires
);
const deps: PackageDependency[] = [];
for (const section of sections) {
let depType = setDepType(section, 'requires');
const rawLines = section.split('\n').filter(isNonEmptyString);
for (const rawLine of rawLines) {
if (!isComment(rawLine)) {
depType = setDepType(rawLine, depType);
// extract all dependencies from each line
const lines = rawLine.split(regEx(/["'],/));
for (const line of lines) {
const matches = regex.exec(line.trim());
if (matches?.groups) {
let dep: PackageDependency = {};
const depName = matches.groups?.name;
const currentValue = matches.groups?.version.trim();
let replaceString = `${depName}/${currentValue}`;
// conan uses @_/_ as a placeholder for no userChannel
let userAndChannel = '@_/_';
if (matches.groups.userChannel) {
userAndChannel = matches.groups.userChannel;
replaceString = `${depName}/${currentValue}${userAndChannel}`;
if (!userAndChannel.includes('/')) {
userAndChannel = `${userAndChannel}/_`;
}
}
const packageName = `${depName}/${currentValue}${userAndChannel}`;
dep = {
...dep,
depName,
packageName,
currentValue,
replaceString,
depType,
};
if (matches.groups.revision) {
dep.currentDigest = matches.groups.revision;
dep.autoReplaceStringTemplate = `{{depName}}/{{newValue}}${userAndChannel}{{#if newDigest}}#{{newDigest}}{{/if}}`;
dep.replaceString = `${replaceString}#${dep.currentDigest}`;
}
deps.push(dep);
}
}
}
}
}
return deps.length ? { deps } : null;
}