UNPKG

renovate

Version:

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

427 lines • 16.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setParseGradleFunc = setParseGradleFunc; exports.handleAssignment = handleAssignment; exports.handleDepString = handleDepString; exports.handleKotlinShortNotationDep = handleKotlinShortNotationDep; exports.handleLongFormDep = handleLongFormDep; exports.handlePlugin = handlePlugin; exports.handleRegistryContent = handleRegistryContent; exports.handleRegistryUrl = handleRegistryUrl; exports.handleLibraryDep = handleLibraryDep; exports.handleApplyFrom = handleApplyFrom; exports.handleImplicitDep = handleImplicitDep; const tslib_1 = require("tslib"); const upath_1 = tslib_1.__importDefault(require("upath")); const logger_1 = require("../../../../logger"); const fs_1 = require("../../../../util/fs"); const regex_1 = require("../../../../util/regex"); const url_1 = require("../../../../util/url"); const utils_1 = require("../utils"); const common_1 = require("./common"); // needed to break circular dependency let parseGradle; function setParseGradleFunc(func) { parseGradle = func; } function handleAssignment(ctx) { const key = (0, common_1.loadFromTokenMap)(ctx, 'keyToken')[0].value; const valTokens = (0, common_1.loadFromTokenMap)(ctx, 'valToken'); if (valTokens.length > 1) { // = template string with multiple variables ctx.tokenMap.templateStringTokens = valTokens; handleDepString(ctx); delete ctx.tokenMap.templateStringTokens; } else if (valTokens[0].type === 'symbol') { // foo = bar || foo = "${bar}" const varData = (0, common_1.findVariable)(valTokens[0].value, ctx); if (varData) { ctx.globalVars[key] = { ...varData }; } } else { // = string value const dep = (0, utils_1.parseDependencyString)(valTokens[0].value); if (dep) { dep.sharedVariableName = key; dep.managerData = { fileReplacePosition: valTokens[0].offset + dep.depName.length + 1, packageFile: ctx.packageFile, }; ctx.deps.push(dep); } ctx.globalVars[key] = { key, value: valTokens[0].value, fileReplacePosition: valTokens[0].offset, packageFile: ctx.packageFile, }; } return ctx; } function handleDepString(ctx) { const stringTokens = (0, common_1.loadFromTokenMap)(ctx, 'templateStringTokens'); const templateString = (0, common_1.interpolateString)(stringTokens, ctx); if (!templateString) { return ctx; } const dep = (0, utils_1.parseDependencyString)(templateString); if (!dep) { return ctx; } let packageFile; let fileReplacePosition; for (const token of stringTokens) { if (token.type === 'symbol') { const varData = (0, common_1.findVariable)(token.value, ctx); if (varData) { packageFile = varData.packageFile; fileReplacePosition = varData.fileReplacePosition; if (varData.value === dep.currentValue) { dep.managerData = { fileReplacePosition, packageFile }; dep.sharedVariableName = varData.key; } } } } if (!dep.managerData) { const lastToken = stringTokens[stringTokens.length - 1]; if (lastToken?.type === 'string-value' && dep.currentValue && lastToken.value.includes(dep.currentValue)) { packageFile = ctx.packageFile; if (stringTokens.length === 1) { fileReplacePosition = lastToken.offset + dep.depName.length + 1; } else { fileReplacePosition = lastToken.offset + lastToken.value.lastIndexOf(dep.currentValue); } delete dep.sharedVariableName; } else { dep.skipReason = 'contains-variable'; } dep.managerData = { fileReplacePosition, packageFile }; } ctx.deps.push(dep); return ctx; } function handleKotlinShortNotationDep(ctx) { const moduleNameTokens = (0, common_1.loadFromTokenMap)(ctx, 'artifactId'); const versionTokens = (0, common_1.loadFromTokenMap)(ctx, 'version'); const moduleName = (0, common_1.interpolateString)(moduleNameTokens, ctx); const versionValue = (0, common_1.interpolateString)(versionTokens, ctx); if (!moduleName || !versionValue) { return ctx; } const groupIdArtifactId = `org.jetbrains.kotlin:kotlin-${moduleName}`; const dep = (0, utils_1.parseDependencyString)(`${groupIdArtifactId}:${versionValue}`); if (!dep) { return ctx; } dep.depName = moduleName; dep.packageName = groupIdArtifactId; dep.managerData = { fileReplacePosition: versionTokens[0].offset, packageFile: ctx.packageFile, }; if (versionTokens.length > 1) { // = template string with multiple variables dep.skipReason = 'unspecified-version'; } else if (versionTokens[0].type === 'symbol') { const varData = (0, common_1.findVariable)(versionTokens[0].value, ctx); if (varData) { dep.sharedVariableName = varData.key; dep.currentValue = varData.value; dep.managerData = { fileReplacePosition: varData.fileReplacePosition, packageFile: varData.packageFile, }; } } ctx.deps.push(dep); return ctx; } function handleLongFormDep(ctx) { const groupIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'groupId'); const artifactIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'artifactId'); const versionTokens = (0, common_1.loadFromTokenMap)(ctx, 'version'); const groupId = (0, common_1.interpolateString)(groupIdTokens, ctx); const artifactId = (0, common_1.interpolateString)(artifactIdTokens, ctx); const version = (0, common_1.interpolateString)(versionTokens, ctx); if (!groupId || !artifactId || !version) { return ctx; } // Special handling: 3 independent dependencies mismatched as groupId, artifactId, version if ((0, utils_1.isDependencyString)(groupId) && (0, utils_1.isDependencyString)(artifactId) && (0, utils_1.isDependencyString)(version)) { ctx.tokenMap.templateStringTokens = groupIdTokens; handleDepString(ctx); ctx.tokenMap.templateStringTokens = artifactIdTokens; handleDepString(ctx); ctx.tokenMap.templateStringTokens = versionTokens; handleDepString(ctx); return ctx; } const dep = (0, utils_1.parseDependencyString)([groupId, artifactId, version].join(':')); if (!dep) { return ctx; } const methodName = ctx.tokenMap.methodName ?? null; if (versionTokens.length > 1) { // = template string with multiple variables dep.skipReason = 'unspecified-version'; } else if (versionTokens[0].type === 'symbol') { const varData = (0, common_1.findVariable)(versionTokens[0].value, ctx); if (varData) { dep.sharedVariableName = varData.key; dep.managerData = { fileReplacePosition: varData.fileReplacePosition, packageFile: varData.packageFile, }; } } else { // = string value if (methodName?.[0]?.value === 'dependencySet') { dep.sharedVariableName = `${groupId}:${version}`; } dep.managerData = { fileReplacePosition: versionTokens[0].offset, packageFile: ctx.packageFile, }; } ctx.deps.push(dep); return ctx; } function handlePlugin(ctx) { const methodName = (0, common_1.loadFromTokenMap)(ctx, 'methodName')[0]; const pluginName = (0, common_1.loadFromTokenMap)(ctx, 'pluginName')[0]; const pluginVersion = (0, common_1.loadFromTokenMap)(ctx, 'version'); const plugin = pluginName.value; const depName = methodName.value === 'kotlin' ? `org.jetbrains.kotlin.${plugin}` : plugin; const packageName = `${depName}:${depName}.gradle.plugin`; const dep = { depType: 'plugin', depName, packageName, commitMessageTopic: `plugin ${depName}`, currentValue: pluginVersion[0].value, managerData: { fileReplacePosition: pluginVersion[0].offset, packageFile: ctx.packageFile, }, }; if (pluginVersion.length > 1) { // = template string with multiple variables dep.skipReason = 'unspecified-version'; } else if (pluginVersion[0].type === 'symbol') { const varData = (0, common_1.findVariable)(pluginVersion[0].value, ctx); if (varData) { dep.sharedVariableName = varData.key; dep.currentValue = varData.value; dep.managerData = { fileReplacePosition: varData.fileReplacePosition, packageFile: varData.packageFile, }; } else { dep.skipReason = 'unspecified-version'; } } ctx.deps.push(dep); return ctx; } function isValidContentDescriptorRegex(fieldName, pattern) { try { (0, regex_1.regEx)(pattern); } catch { logger_1.logger.debug(`Skipping content descriptor with unsupported regExp pattern for ${fieldName}: ${pattern}`); return false; } return true; } function handleRegistryContent(ctx) { const methodName = (0, common_1.loadFromTokenMap)(ctx, 'methodName')[0].value; let groupId = (0, common_1.loadFromTokenMap)(ctx, 'groupId')[0].value; let matcher = 'simple'; if (methodName.includes('Regex')) { matcher = 'regex'; groupId = `^${groupId}$`.replaceAll('\\\\', '\\'); if (!isValidContentDescriptorRegex('group', groupId)) { return ctx; } } else if (methodName.includes('AndSubgroups')) { matcher = 'subgroup'; } const mode = methodName.startsWith('include') ? 'include' : 'exclude'; const spec = { mode, matcher, groupId }; if (methodName.includes('Module') || methodName.includes('Version')) { spec.artifactId = (0, common_1.loadFromTokenMap)(ctx, 'artifactId')[0].value; if (matcher === 'regex') { spec.artifactId = `^${spec.artifactId}$`.replaceAll('\\\\', '\\'); if (!isValidContentDescriptorRegex('module', spec.artifactId)) { return ctx; } } } if (methodName.includes('Version')) { spec.version = (0, common_1.loadFromTokenMap)(ctx, 'version')[0].value; if (matcher === 'regex') { spec.version = `^${spec.version}$`.replaceAll('\\\\', '\\'); if (!isValidContentDescriptorRegex('version', spec.version)) { return ctx; } } } ctx.tmpRegistryContent.push(spec); return ctx; } function isPluginRegistry(ctx) { if (ctx.tokenMap.registryScope) { const registryScope = (0, common_1.loadFromTokenMap)(ctx, 'registryScope')[0].value; return registryScope === 'pluginManagement'; } return false; } function isExclusiveRegistry(ctx) { if (ctx.tokenMap.registryType) { const registryType = (0, common_1.loadFromTokenMap)(ctx, 'registryType')[0].value; return registryType === 'exclusiveContent'; } return false; } function handleRegistryUrl(ctx) { let localVariables = ctx.globalVars; if (ctx.tokenMap.name) { const nameTokens = (0, common_1.loadFromTokenMap)(ctx, 'name'); const nameValue = (0, common_1.interpolateString)(nameTokens, ctx, localVariables); if (nameValue) { localVariables = { ...localVariables, name: { key: 'name', value: nameValue, }, }; } } let registryUrl = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'registryUrl'), ctx, localVariables); if (registryUrl) { registryUrl = registryUrl.replace((0, regex_1.regEx)(/\\/g), ''); const url = (0, url_1.parseUrl)(registryUrl); if (url?.host && url.protocol) { ctx.registryUrls.push({ registryUrl, registryType: isExclusiveRegistry(ctx) ? 'exclusive' : 'regular', scope: isPluginRegistry(ctx) ? 'plugin' : 'dep', content: ctx.tmpRegistryContent, }); } } return ctx; } function handleLibraryDep(ctx) { const groupIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'groupId'); const artifactIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'artifactId'); const groupId = (0, common_1.interpolateString)(groupIdTokens, ctx); const artifactId = (0, common_1.interpolateString)(artifactIdTokens, ctx); if (!groupId || !artifactId) { return ctx; } const aliasToken = (0, common_1.loadFromTokenMap)(ctx, 'alias')[0]; const key = `libs.${aliasToken.value.replace((0, regex_1.regEx)(/[-_]/g), '.')}`; ctx.globalVars[key] = { key, value: `${groupId}:${artifactId}`, fileReplacePosition: aliasToken.offset, packageFile: ctx.packageFile, }; if (ctx.tokenMap.version) { const version = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'version'), ctx); if (version) { handleLongFormDep(ctx); } } return ctx; } function handleApplyFrom(ctx) { let scriptFile = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'scriptFile'), ctx); if (!scriptFile) { return ctx; } if (ctx.tokenMap.parentPath) { const parentPath = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'parentPath'), ctx); if (parentPath && scriptFile) { scriptFile = upath_1.default.join(parentPath, scriptFile); } } if (ctx.recursionDepth > 2) { logger_1.logger.debug(`Max recursion depth reached in script file: ${scriptFile}`); return ctx; } if (!(0, regex_1.regEx)(/\.gradle(\.kts)?$/).test(scriptFile)) { logger_1.logger.debug({ scriptFile }, `Only Gradle files can be included`); return ctx; } const scriptFilePath = (0, fs_1.getSiblingFileName)(ctx.packageFile, scriptFile); if (!ctx.fileContents[scriptFilePath]) { logger_1.logger.debug(`Failed to process included Gradle file ${scriptFilePath}`); return ctx; } const matchResult = parseGradle( // TODO #22198 ctx.fileContents[scriptFilePath], ctx.globalVars, scriptFilePath, ctx.fileContents, ctx.recursionDepth + 1); ctx.deps.push(...matchResult.deps); ctx.globalVars = { ...ctx.globalVars, ...matchResult.vars }; ctx.registryUrls.push(...matchResult.urls); return ctx; } function handleImplicitDep(ctx) { const implicitDepName = (0, common_1.loadFromTokenMap)(ctx, 'implicitDepName')[0].value; const versionTokens = (0, common_1.loadFromTokenMap)(ctx, 'version'); const versionValue = (0, common_1.interpolateString)(versionTokens, ctx); if (!versionValue) { return ctx; } const isImplicitGradlePlugin = implicitDepName in common_1.GRADLE_PLUGINS; const groupIdArtifactId = isImplicitGradlePlugin ? common_1.GRADLE_PLUGINS[implicitDepName][1] : common_1.GRADLE_TEST_SUITES[implicitDepName]; const dep = (0, utils_1.parseDependencyString)(`${groupIdArtifactId}:${versionValue}`); if (!dep) { return ctx; } dep.depName = implicitDepName; dep.packageName = groupIdArtifactId; dep.managerData = { fileReplacePosition: versionTokens[0].offset, packageFile: ctx.packageFile, }; if (versionTokens.length > 1) { // = template string with multiple variables dep.skipReason = 'unspecified-version'; } else if (versionTokens[0].type === 'symbol') { const varData = (0, common_1.findVariable)(versionTokens[0].value, ctx); if (varData) { dep.sharedVariableName = varData.key; dep.currentValue = varData.value; dep.managerData = { fileReplacePosition: varData.fileReplacePosition, packageFile: varData.packageFile, }; } } ctx.deps.push(dep); return ctx; } //# sourceMappingURL=handlers.js.map