UNPKG

renovate

Version:

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

278 lines (277 loc) • 10.2 kB
import { newlineRegex, regEx } from "../../../util/regex.js"; import { logger } from "../../../logger/index.js"; import { parseUrl } from "../../../util/url.js"; import { readLocalFile } from "../../../util/fs/index.js"; import { id } from "../../versioning/semver/index.js"; import { id as id$1 } from "../../versioning/maven/index.js"; import { get } from "../../versioning/index.js"; import { MAVEN_REPO } from "../../datasource/maven/common.js"; import { MavenDatasource } from "../../datasource/maven/index.js"; import { GithubReleasesDatasource } from "../../datasource/github-releases/index.js"; import { SbtPackageDatasource } from "../../datasource/sbt-package/index.js"; import { SBT_PLUGINS_REPO, SbtPluginDatasource } from "../../datasource/sbt-plugin/index.js"; import { normalizeScalaVersion, sortPackageFiles } from "./util.js"; import { lang, query } from "@renovatebot/good-enough-parser"; //#region lib/modules/manager/sbt/extract.ts const scala = lang.createLang("scala"); const sbtVersionRegex = regEx("sbt\\.version *= *(?<version>\\d+\\.\\d+\\.\\d+)"); const sbtProxyUrlRegex = regEx(/^\s*(?<repoName>\S+):\s+(?<proxy>https?:\/\/[\w./-]+)/); const scalaVersionMatch = query.sym("scalaVersion").op(":=").alt(query.sym((ctx, { value: currentVarName }) => ({ ...ctx, currentVarName })).op(".").sym((ctx, { value: varName }) => { const dottedVariableName = `${ctx.currentVarName}.${varName}`; const currentValue = ctx.vars[dottedVariableName]; if (currentValue) ctx.scalaVersion = currentValue; delete ctx.currentVarName; return ctx; }), query.sym((ctx, { value: varName }) => { const scalaVersion = ctx.vars[varName]; if (scalaVersion) ctx.scalaVersion = scalaVersion; return ctx; }), query.str((ctx, { value: scalaVersion }) => ({ ...ctx, scalaVersion }))).handler((ctx) => { if (ctx.scalaVersion) { const version = get(id$1); let packageName = "org.scala-lang:scala-library"; if (version.getMajor(ctx.scalaVersion) === 3) packageName = "org.scala-lang:scala3-library_3"; const dep = { datasource: MavenDatasource.id, depName: "scala", packageName, currentValue: ctx.scalaVersion, separateMinorPatch: true }; ctx.scalaVersion = normalizeScalaVersion(ctx.scalaVersion); ctx.deps.push(dep); } return ctx; }); const packageFileVersionMatch = query.sym("version").op(":=").alt(query.str((ctx, { value: packageFileVersion }) => ({ ...ctx, packageFileVersion })), query.sym((ctx, { value: varName }) => { const packageFileVersion = ctx.vars[varName]; if (packageFileVersion) ctx.packageFileVersion = packageFileVersion; return ctx; })); const variableNameMatch = query.sym((ctx, { value: varName }) => ({ ...ctx, currentVarName: varName })).opt(query.op(":").sym("String")); const variableValueMatch = query.str((ctx, { value }) => { ctx.vars[ctx.currentVarName] = value; delete ctx.currentVarName; return ctx; }); const assignmentMatch = query.sym("val").join(variableNameMatch).op("="); const variableDefinitionMatch = query.alt(query.sym("lazy").join(assignmentMatch), assignmentMatch, variableNameMatch.op(":=")).join(variableValueMatch); const objectFieldMatch = query.sym((ctx, { value: fieldName }) => ({ ...ctx, currentVarName: `${ctx.currentObjectName}.${fieldName}` })).op("=").str((ctx, { value }) => { ctx.vars[ctx.currentVarName] = value; delete ctx.currentVarName; return ctx; }); const objectAssignmentMatch = query.sym("val").sym((ctx, { value: currentObjectName }) => ({ ...ctx, currentObjectName })).op("=").sym("new").tree({ search: query.many(objectFieldMatch) }).handler((ctx) => { delete ctx.currentObjectName; return ctx; }); const groupIdMatch = query.alt(query.sym((ctx, { value: varName }) => { const currentGroupId = ctx.vars[varName]; if (currentGroupId) ctx.groupId = currentGroupId; return ctx; }), query.str((ctx, { value: groupId }) => ({ ...ctx, groupId }))); const artifactIdMatch = query.alt(query.sym((ctx, { value }) => { const artifactId = ctx.vars[value]; if (artifactId) ctx.artifactId = artifactId; return ctx; }), query.str((ctx, { value: artifactId }) => ({ ...ctx, artifactId }))); const versionMatch = query.alt(query.sym((ctx, { value: currentVarName }) => ({ ...ctx, currentVarName })).op(".").sym((ctx, { value: varName }) => { const dottedVariableName = `${ctx.currentVarName}.${varName}`; const currentValue = ctx.vars[dottedVariableName]; if (currentValue) { ctx.currentValue = currentValue; ctx.variableName = dottedVariableName; } delete ctx.currentVarName; return ctx; }), query.sym((ctx, { value: varName }) => { const currentValue = ctx.vars[varName]; if (currentValue) { ctx.currentValue = currentValue; ctx.variableName = varName; } return ctx; }), query.str((ctx, { value: currentValue }) => ({ ...ctx, currentValue }))); const simpleDependencyMatch = groupIdMatch.op("%").join(artifactIdMatch).op("%").join(versionMatch); const versionedDependencyMatch = groupIdMatch.op("%%").join(artifactIdMatch).handler((ctx) => ({ ...ctx, useScalaVersion: true })).op("%").join(versionMatch); const crossDependencyMatch = groupIdMatch.op("%%%").join(artifactIdMatch).handler((ctx) => ({ ...ctx, useScalaVersion: true })).op("%").join(versionMatch); function depHandler(ctx) { const { scalaVersion, groupId, artifactId, currentValue, useScalaVersion, depType, variableName } = ctx; delete ctx.groupId; delete ctx.artifactId; delete ctx.currentValue; delete ctx.useScalaVersion; delete ctx.depType; delete ctx.variableName; const depName = `${groupId}:${artifactId}`; const dep = { datasource: SbtPackageDatasource.id, depName, packageName: scalaVersion && useScalaVersion ? `${depName}_${scalaVersion}` : depName, currentValue }; if (depType) dep.depType = depType; if (depType === "plugin") dep.datasource = SbtPluginDatasource.id; if (variableName) { dep.sharedVariableName = variableName; dep.variableName = variableName; } ctx.deps.push(dep); return ctx; } function depTypeHandler(ctx, { value: depType }) { return { ...ctx, depType }; } const sbtPackageMatch = query.opt(query.opt(query.sym("lazy")).sym("val").sym().op("=")).alt(crossDependencyMatch, simpleDependencyMatch, versionedDependencyMatch).opt(query.alt(query.sym("classifier").str(depTypeHandler), query.op("%").sym(depTypeHandler), query.op("%").str(depTypeHandler))).handler(depHandler); const sbtPluginMatch = query.sym(regEx(/^(?:addSbtPlugin|addCompilerPlugin)$/)).tree({ type: "wrapped-tree", maxDepth: 1, search: query.begin().alt(simpleDependencyMatch, versionedDependencyMatch).end() }).handler((ctx) => ({ ...ctx, depType: "plugin" })).handler(depHandler); const resolverMatch = query.str().sym("at").str((ctx, { value }) => { if (parseUrl(value)) ctx.registryUrls.push(value); return ctx; }); const addResolverMatch = query.sym("resolvers").alt(query.op("+=").join(resolverMatch), query.op("++=").sym("Seq").tree({ type: "wrapped-tree", maxDepth: 1, search: resolverMatch })); function registryUrlHandler(ctx) { for (const dep of ctx.deps) dep.registryUrls = [...ctx.registryUrls]; return ctx; } const query$1 = query.tree({ type: "root-tree", maxDepth: 32, search: query.alt(scalaVersionMatch, packageFileVersionMatch, sbtPackageMatch, sbtPluginMatch, addResolverMatch, variableDefinitionMatch, objectAssignmentMatch), postHandler: registryUrlHandler }); function extractProxyUrls(content, packageFile) { const extractedProxyUrls = []; logger.debug(`Parsing proxy repository file ${packageFile}`); for (const line of content.split(newlineRegex)) { const extraction = sbtProxyUrlRegex.exec(line); if (extraction?.groups?.proxy) extractedProxyUrls.push(extraction.groups.proxy); else if (line.trim() === "maven-central") extractedProxyUrls.push(MAVEN_REPO); } return extractedProxyUrls; } function extractPackageFile(content, packageFile) { return extractPackageFileInternal(content, packageFile); } function extractPackageFileInternal(content, packageFile, ctxScalaVersion) { if (packageFile === "project/build.properties" || packageFile.endsWith("/project/build.properties")) { const regexResult = sbtVersionRegex.exec(content); const sbtVersion = regexResult?.groups?.version; const matchString = regexResult?.[0]; if (sbtVersion) return { deps: [{ datasource: GithubReleasesDatasource.id, depName: "sbt/sbt", packageName: "sbt/sbt", versioning: id, currentValue: sbtVersion, replaceString: matchString, extractVersion: "^v(?<version>\\S+)", registryUrls: [] }] }; else return null; } let parsedResult = null; try { parsedResult = scala.query(content, query$1, { vars: {}, deps: [], registryUrls: [], scalaVersion: ctxScalaVersion }); } catch (err) /* istanbul ignore next */ { logger.debug({ err, packageFile }, "Sbt parsing error"); } if (!parsedResult) return null; const { deps, scalaVersion, packageFileVersion } = parsedResult; if (!deps.length) return null; return { deps, packageFileVersion, managerData: { scalaVersion } }; } async function extractAllPackageFiles(_config, packageFiles) { const packages = []; const proxyUrls = []; let ctxScalaVersion; const sortedPackageFiles = sortPackageFiles(packageFiles); for (const packageFile of sortedPackageFiles) { const content = await readLocalFile(packageFile, "utf8"); if (!content) { logger.debug({ packageFile }, "packageFile has no content"); continue; } if (packageFile === "repositories") { const urls = extractProxyUrls(content, packageFile); proxyUrls.push(...urls); } else { const pkg = extractPackageFileInternal(content, packageFile, ctxScalaVersion); if (pkg) { packages.push({ deps: pkg.deps, packageFile }); if (pkg.managerData?.scalaVersion) ctxScalaVersion = pkg.managerData.scalaVersion; } } } for (const pkg of packages) for (const dep of pkg.deps) if (dep.datasource !== GithubReleasesDatasource.id) if (proxyUrls.length > 0) dep.registryUrls.unshift(...proxyUrls); else if (dep.depType === "plugin") dep.registryUrls.unshift(SBT_PLUGINS_REPO, MAVEN_REPO); else dep.registryUrls.unshift(MAVEN_REPO); return packages; } //#endregion export { extractAllPackageFiles, extractPackageFile }; //# sourceMappingURL=extract.js.map