renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
128 lines (127 loc) • 5.82 kB
JavaScript
import { regEx } from "../../../util/regex.js";
import { logger } from "../../../logger/index.js";
import { readLocalFile } from "../../../util/fs/index.js";
import { getLockFileName, getLockedVersion } from "./lockfile.js";
import { createAquaToolConfig, createCargoToolConfig, createDotnetToolConfig, createGemToolConfig, createGithubToolConfig, createGoToolConfig, createNpmToolConfig, createPipxToolConfig, createSpmToolConfig, createUbiToolConfig } from "./backends.js";
import { MiseLockFile } from "./schema.js";
import { asdfTooling, getOrderedMiseRegistryBackends, miseTooling } from "./upgradeable-tooling.js";
import { parseTomlFile } from "./utils.js";
import { isArray, isFunction, isNonEmptyObject, isNonEmptyString, isObject, isString } from "@sindresorhus/is";
//#region lib/modules/manager/mise/extract.ts
const optionInToolNameRegex = regEx(/^(?<name>.+?)(?:\[(?<options>.+)\])?$/);
/**
* Extracts mise tool dependencies from a mise configuration file.
* Supports various backends (core, asdf, aqua, cargo, etc.) and
* extracts locked versions when a corresponding lock file exists.
*/
async function extractPackageFile(content, packageFile) {
logger.trace(`mise.extractPackageFile(${packageFile})`);
const misefile = parseTomlFile(content, packageFile);
if (!misefile) return null;
const deps = [];
for (const [name, toolData] of Object.entries(misefile.tools)) deps.push(extractToolEntry(name, toolData));
for (const taskData of Object.values(misefile.tasks)) for (const [name, toolData] of Object.entries(taskData.tools ?? {})) deps.push(extractToolEntry(name, toolData));
if (!deps.length) return null;
const result = { deps };
const lockFileName = getLockFileName(packageFile);
const lockFileContent = await readLocalFile(lockFileName, "utf8");
if (lockFileContent) {
const lockFileParsed = MiseLockFile.safeParse(lockFileContent);
if (lockFileParsed.success) {
result.lockFiles = [lockFileName];
for (const dep of deps) {
const lockedVersion = getLockedVersion(lockFileParsed.data, dep.depName);
if (lockedVersion) dep.lockedVersion = lockedVersion;
}
} else logger.debug({
lockFileName,
error: lockFileParsed.error
}, "Failed to parse mise lock file");
}
return result;
}
function parseVersion(toolData) {
if (isNonEmptyString(toolData)) return toolData;
if (isArray(toolData, isString)) return toolData.length ? toolData[0] : null;
if (isObject(toolData) && isNonEmptyString(toolData.version)) return toolData.version;
return null;
}
function parseOptions(optionsInName, toolOptions) {
return {
...isNonEmptyString(optionsInName) ? Object.fromEntries(optionsInName.split(",").map((option) => option.split("=", 2))) : {},
...toolOptions
};
}
function getToolConfig(backend, toolName, version, toolOptions) {
switch (backend) {
case "": {
const staticResult = getRegistryToolConfig(toolName, version);
if (staticResult) return staticResult;
const backends = getOrderedMiseRegistryBackends(toolName);
if (backends.github) {
const result = getToolConfig("github", backends.github, version, toolOptions);
// v8 ignore else -- TODO: add test #40625
if (result !== null) return result;
}
for (const [backendType, backendName] of Object.entries(backends)) {
const result = getToolConfig(backendType, backendName, version, toolOptions);
// v8 ignore else -- TODO: add test #40625
if (result !== null) return result;
}
return null;
}
case "core": return getConfigFromTooling(miseTooling, toolName, version);
case "asdf": return getConfigFromTooling(asdfTooling, toolName, version);
case "vfox": return getRegistryToolConfig(toolName, version);
case "aqua": return getRegistryToolConfig(toolName, version) ?? createAquaToolConfig(toolName, version);
case "cargo": return createCargoToolConfig(toolName, version);
case "dotnet": return createDotnetToolConfig(toolName);
case "gem": return createGemToolConfig(toolName);
case "github": return createGithubToolConfig(toolName, version, toolOptions);
case "go": return createGoToolConfig(toolName);
case "npm": return createNpmToolConfig(toolName);
case "pipx": return createPipxToolConfig(toolName);
case "spm": return createSpmToolConfig(toolName);
case "ubi": return createUbiToolConfig(toolName, version, toolOptions);
default: return null;
}
}
/**
* Get the tooling config for a short name defined in the default registry
* @link https://mise.jdx.dev/registry.html
*/
function getRegistryToolConfig(short, version) {
return getConfigFromTooling(miseTooling, short, version) ?? getConfigFromTooling(asdfTooling, short, version);
}
function getConfigFromTooling(toolingSource, name, version) {
const toolDefinition = toolingSource[name];
if (!toolDefinition) return null;
return (isFunction(toolDefinition.config) ? toolDefinition.config(version) : toolDefinition.config) ?? null;
}
function extractToolEntry(name, toolData) {
const version = parseVersion(toolData);
const { name: depName, options: optionsInName } = optionInToolNameRegex.exec(name.trim()).groups;
const delimiterIndex = depName.indexOf(":");
const backend = depName.substring(0, delimiterIndex);
const toolName = depName.substring(delimiterIndex + 1);
const options = parseOptions(optionsInName, isNonEmptyObject(toolData) ? toolData : {});
return createDependency(depName, version, version === null ? null : getToolConfig(backend, toolName, version, options));
}
function createDependency(name, version, config) {
if (version === null) return {
depName: name,
skipReason: "unspecified-version"
};
if (config === null) return {
depName: name,
skipReason: "unsupported-datasource"
};
return {
depName: name,
currentValue: version,
...config
};
}
//#endregion
export { extractPackageFile };
//# sourceMappingURL=extract.js.map