UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

162 lines (161 loc) • 5.58 kB
import { regEx } from "../../../util/regex.js"; import { logger } from "../../../logger/index.js"; import { getSiblingFileName, localPathExists } from "../../../util/fs/index.js"; import { isVersion } from "../../versioning/semver/index.js"; import { NugetDatasource } from "../../datasource/nuget/index.js"; import { getDep } from "../dockerfile/extract.js"; import { applyRegistries, findVersion, getConfiguredRegistries, isXmlElement } from "./util.js"; import { extractMsbuildGlobalManifest } from "./extract/global-manifest.js"; import { extractPackagesFromSingleCsharpFile } from "./extract/single-csharp-file.js"; import { isNonEmptyStringAndNotWhitespace, isString } from "@sindresorhus/is"; import { XmlDocument } from "xmldoc"; //#region lib/modules/manager/nuget/extract.ts /** * https://learn.microsoft.com/nuget/concepts/package-versioning * This article mentions that Nuget 3.x and later tries to restore the lowest possible version * regarding to given version range. * 1.3.4 equals [1.3.4,) */ const elemNames = new Set([ "PackageReference", "PackageVersion", "DotNetCliToolReference", "GlobalPackageReference" ]); function extractDepsFromXml(xmlNode) { const results = []; const vars = /* @__PURE__ */ new Map(); const todo = [xmlNode]; while (todo.length) { const child = todo.pop(); const { name, attr } = child; if (name === "ContainerBaseImage") { const { depName, ...dep } = getDep(child.val, true); if (isNonEmptyStringAndNotWhitespace(depName)) results.push({ ...dep, depName, depType: "docker" }); } else if (elemNames.has(name)) { const depName = attr?.Include || attr?.Update; if (!depName) continue; const dep = { datasource: NugetDatasource.id, depType: "nuget", depName }; let currentValue = attr?.Version ?? attr?.version ?? child.valueWithPath("Version") ?? attr?.VersionOverride ?? child.valueWithPath("VersionOverride"); if (!isNonEmptyStringAndNotWhitespace(currentValue)) dep.skipReason = "invalid-version"; let sharedVariableName; currentValue = currentValue?.trim()?.replace(/^\$\((\w+)\)$/, (match, key) => { sharedVariableName = key; const val = vars.get(key); if (val) return val; return match; }); if (sharedVariableName) if (currentValue === `$(${sharedVariableName})`) dep.skipReason = "contains-variable"; else dep.sharedVariableName = sharedVariableName; dep.currentValue = currentValue; results.push(dep); } else if (name === "Sdk") { const depName = attr?.Name; const version = attr?.Version; if (depName && version) results.push({ depName, currentValue: version, depType: "msbuild-sdk", datasource: NugetDatasource.id }); } else if (name === "Import") { const depName = attr?.Sdk; const version = attr?.Version; if (depName && version) results.push({ depName, currentValue: version, depType: "msbuild-sdk", datasource: NugetDatasource.id }); } else { if (name === "Project") { if (attr?.Sdk) { const [name, version] = (attr?.Sdk).split("/"); if (name && version) results.push({ depName: name, depType: "msbuild-sdk", currentValue: version, datasource: NugetDatasource.id }); } const propertyGroup = child.childNamed("PropertyGroup"); if (propertyGroup) { for (const propChild of propertyGroup.children) if (isXmlElement(propChild)) { const { name, val } = propChild; if (!["Version", "TargetFramework"].includes(name)) vars.set(name, val); } } } todo.push(...child.children.filter(isXmlElement)); } } return results; } async function extractPackageFile(content, packageFile, _config) { logger.trace(`nuget.extractPackageFile(${packageFile})`); const registries = await getConfiguredRegistries(packageFile); if (packageFile.endsWith("dotnet-tools.json")) { const deps = []; let manifest; try { manifest = JSON.parse(content); } catch { logger.debug({ packageFile }, `Invalid JSON`); return null; } if (manifest.version !== 1) { logger.debug({ packageFile }, "Unsupported dotnet tools version"); return null; } for (const depName of Object.keys(manifest.tools ?? {})) { const currentValue = manifest.tools[depName].version; const dep = { depType: "nuget", depName, currentValue, datasource: NugetDatasource.id }; if (isString(currentValue) && isVersion(currentValue)) dep.versioning = "semver"; applyRegistries(dep, registries); deps.push(dep); } return deps.length ? { deps } : null; } if (packageFile.endsWith("global.json")) return extractMsbuildGlobalManifest(content, packageFile, registries); if (packageFile.endsWith(".cs")) return extractPackagesFromSingleCsharpFile(content, packageFile, registries); if (!regEx(/^\s*<.+>$/m).test(content.trim())) { logger.debug(`NuGet: Skipping ${packageFile} as it is not XML`); return null; } let deps = []; let packageFileVersion; try { const parsedXml = new XmlDocument(content); deps = extractDepsFromXml(parsedXml).map((dep) => applyRegistries(dep, registries)); packageFileVersion = findVersion(parsedXml)?.val; } catch (err) { logger.debug({ err, packageFile }, `Failed to parse XML`); } if (!deps.length) return null; const res = { deps, packageFileVersion }; const lockFileName = getSiblingFileName(packageFile, "packages.lock.json"); if (await localPathExists(lockFileName)) res.lockFiles = [lockFileName]; return res; } //#endregion export { extractPackageFile }; //# sourceMappingURL=extract.js.map