UNPKG

renovate

Version:

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

273 lines • 12.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractPackageFile = extractPackageFile; const tslib_1 = require("tslib"); const is_1 = tslib_1.__importDefault(require("@sindresorhus/is")); const logger_1 = require("../../../logger"); const fs_1 = require("../../../util/fs"); const regex_1 = require("../../../util/regex"); const url_1 = require("../../../util/url"); const git_refs_1 = require("../../datasource/git-refs"); const ruby_version_1 = require("../../datasource/ruby-version"); const rubygems_1 = require("../../datasource/rubygems"); const common_1 = require("./common"); const locked_version_1 = require("./locked-version"); function formatContent(input) { return input.replace((0, regex_1.regEx)(/^ {2}/), '') + '\n'; //remove leading whitespace and add a new line at the end } const variableMatchRegex = (0, regex_1.regEx)(`^(?<key>\\w+)\\s*=\\s*['"](?<value>[^'"]+)['"]`); const gemMatchRegex = (0, regex_1.regEx)(`^\\s*gem\\s+(['"])(?<depName>[^'"]+)(['"])(\\s*,\\s*(?<currentValue>(['"])[^'"]+['"](\\s*,\\s*['"][^'"]+['"])?))?`); const sourceMatchRegex = (0, regex_1.regEx)(`source:\\s*((?:['"](?<registryUrl>[^'"]+)['"])|(?<sourceName>\\w+))?`); const gitRefsMatchRegex = (0, regex_1.regEx)(`((git:\\s*['"](?<gitUrl>[^'"]+)['"])|(\\s*,\\s*github:\\s*['"](?<repoName>[^'"]+)['"]))(\\s*,\\s*branch:\\s*['"](?<branchName>[^'"]+)['"])?(\\s*,\\s*ref:\\s*['"](?<refName>[^'"]+)['"])?(\\s*,\\s*tag:\\s*['"](?<tagName>[^'"]+)['"])?`); const pathMatchRegex = (0, regex_1.regEx)(`path:\\s*['"](?<path>[^'"]+)['"]`); async function extractPackageFile(content, packageFile) { let lineNumber; async function processGroupBlock(line, repositoryUrl, trimGroupLine = false) { const groupMatch = (0, regex_1.regEx)(/^group\s+(.*?)\s+do/).exec(line); if (groupMatch) { const depTypes = groupMatch[1] .split(',') .map((group) => group.trim()) .map((group) => group.replace((0, regex_1.regEx)(/^:/), '')); const groupLineNumber = lineNumber; let groupContent = ''; let groupLine = ''; while (lineNumber < lines.length && (trimGroupLine ? groupLine.trim() !== 'end' : groupLine !== 'end')) { lineNumber += 1; groupLine = lines[lineNumber]; // istanbul ignore if if (!is_1.default.string(groupLine)) { logger_1.logger.debug({ content, packageFile, type: 'groupLine' }, 'Bundler parsing error'); groupLine = 'end'; } if (trimGroupLine ? groupLine.trim() !== 'end' : groupLine !== 'end') { groupContent += formatContent(groupLine); } } const groupRes = await extractPackageFile(groupContent); if (groupRes) { res.deps = res.deps.concat(groupRes.deps.map((dep) => { const depObject = { ...dep, depTypes, managerData: { lineNumber: Number(dep.managerData?.lineNumber) + groupLineNumber + 1, }, }; if (repositoryUrl) { depObject.registryUrls = [repositoryUrl]; } return depObject; })); } } } const res = { registryUrls: [], deps: [], }; const variables = {}; const lines = content.split(regex_1.newlineRegex); for (lineNumber = 0; lineNumber < lines.length; lineNumber += 1) { const line = lines[lineNumber]; let sourceMatch = null; for (const delimiter of common_1.delimiters) { sourceMatch = sourceMatch ?? (0, regex_1.regEx)(`^source ((${delimiter}(?<registryUrl>[^${delimiter}]+)${delimiter})|(?<sourceName>\\w+))\\s*$`).exec(line); } if (sourceMatch) { if (sourceMatch.groups?.registryUrl) { res.registryUrls?.push(sourceMatch.groups.registryUrl); } if (sourceMatch.groups?.sourceName) { const registryUrl = variables[sourceMatch.groups.sourceName]; if (registryUrl) { res.registryUrls?.push(registryUrl); } } } const rubyMatch = (0, common_1.extractRubyVersion)(line); if (rubyMatch) { res.deps.push({ depName: 'ruby', currentValue: rubyMatch, datasource: ruby_version_1.RubyVersionDatasource.id, registryUrls: null, }); } const variableMatch = variableMatchRegex.exec(line); if (variableMatch) { if (variableMatch.groups?.key) { variables[variableMatch.groups?.key] = variableMatch.groups?.value; } } const gemMatch = gemMatchRegex.exec(line)?.groups; if (gemMatch) { const dep = { depName: gemMatch.depName, managerData: { lineNumber }, datasource: rubygems_1.RubygemsDatasource.id, }; if (gemMatch.currentValue) { const currentValue = gemMatch.currentValue; dep.currentValue = currentValue; } const pathMatch = pathMatchRegex.exec(line)?.groups; if (pathMatch) { dep.skipReason = 'internal-package'; } const sourceMatch = sourceMatchRegex.exec(line)?.groups; if (sourceMatch) { if (sourceMatch.registryUrl) { dep.registryUrls = [sourceMatch.registryUrl]; } else if (sourceMatch.sourceName) { dep.registryUrls = [variables[sourceMatch.sourceName]]; } } const gitRefsMatch = gitRefsMatchRegex.exec(line)?.groups; if (gitRefsMatch) { if (gitRefsMatch.gitUrl) { const gitUrl = gitRefsMatch.gitUrl; dep.packageName = gitUrl; if ((0, url_1.isHttpUrl)(gitUrl)) { dep.sourceUrl = gitUrl.replace(/\.git$/, ''); } } else if (gitRefsMatch.repoName) { dep.packageName = `https://github.com/${gitRefsMatch.repoName}`; dep.sourceUrl = dep.packageName; } if (gitRefsMatch.refName) { dep.currentDigest = gitRefsMatch.refName; } else if (gitRefsMatch.branchName) { dep.currentValue = gitRefsMatch.branchName; } else if (gitRefsMatch.tagName) { dep.currentValue = gitRefsMatch.tagName; } dep.datasource = git_refs_1.GitRefsDatasource.id; } res.deps.push(dep); } await processGroupBlock(line); for (const delimiter of common_1.delimiters) { const sourceBlockMatch = (0, regex_1.regEx)(`^source\\s+((${delimiter}(?<registryUrl>[^${delimiter}]+)${delimiter})|(?<sourceName>\\w+))\\s+do`).exec(line); if (sourceBlockMatch) { let repositoryUrl = ''; if (sourceBlockMatch.groups?.registryUrl) { repositoryUrl = sourceBlockMatch.groups.registryUrl; } if (sourceBlockMatch.groups?.sourceName) { if (variables[sourceBlockMatch.groups.sourceName]) { repositoryUrl = variables[sourceBlockMatch.groups.sourceName]; } } const sourceLineNumber = lineNumber; let sourceContent = ''; let sourceLine = ''; while (lineNumber < lines.length && sourceLine.trim() !== 'end') { lineNumber += 1; sourceLine = lines[lineNumber]; // istanbul ignore if if (!is_1.default.string(sourceLine)) { logger_1.logger.debug({ content, packageFile, type: 'sourceLine' }, 'Bundler parsing error'); sourceLine = 'end'; } await processGroupBlock(sourceLine.trim(), repositoryUrl, true); if (sourceLine.trim() !== 'end') { sourceContent += formatContent(sourceLine); } } const sourceRes = await extractPackageFile(sourceContent); if (sourceRes) { res.deps = res.deps.concat(sourceRes.deps.map((dep) => ({ ...dep, registryUrls: [repositoryUrl], managerData: { lineNumber: Number(dep.managerData?.lineNumber) + sourceLineNumber + 1, }, }))); } } } const platformsMatch = (0, regex_1.regEx)(/^platforms\s+(.*?)\s+do/).test(line); if (platformsMatch) { const platformsLineNumber = lineNumber; let platformsContent = ''; let platformsLine = ''; while (lineNumber < lines.length && platformsLine !== 'end') { lineNumber += 1; platformsLine = lines[lineNumber]; // istanbul ignore if if (!is_1.default.string(platformsLine)) { logger_1.logger.debug({ content, packageFile, type: 'platformsLine' }, 'Bundler parsing error'); platformsLine = 'end'; } if (platformsLine !== 'end') { platformsContent += formatContent(platformsLine); } } const platformsRes = await extractPackageFile(platformsContent); if (platformsRes) { res.deps = res.deps.concat(platformsRes.deps.map((dep) => ({ ...dep, managerData: { lineNumber: Number(dep.managerData?.lineNumber) + platformsLineNumber + 1, }, }))); } } const ifMatch = (0, regex_1.regEx)(/^if\s+(.*?)/).test(line); if (ifMatch) { const ifLineNumber = lineNumber; let ifContent = ''; let ifLine = ''; while (lineNumber < lines.length && ifLine !== 'end') { lineNumber += 1; ifLine = lines[lineNumber]; // istanbul ignore if if (!is_1.default.string(ifLine)) { logger_1.logger.debug({ content, packageFile, type: 'ifLine' }, 'Bundler parsing error'); ifLine = 'end'; } if (ifLine !== 'end') { ifContent += formatContent(ifLine); } } const ifRes = await extractPackageFile(ifContent); if (ifRes) { res.deps = res.deps.concat(ifRes.deps.map((dep) => ({ ...dep, managerData: { lineNumber: Number(dep.managerData?.lineNumber) + ifLineNumber + 1, }, }))); } } } if (!res.deps.length && !res.registryUrls?.length) { return null; } if (packageFile) { const gemfileLockPath = await (0, common_1.getLockFilePath)(packageFile); const lockContent = await (0, fs_1.readLocalFile)(gemfileLockPath, 'utf8'); if (lockContent) { logger_1.logger.debug(`Found lock file ${gemfileLockPath} for packageFile: ${packageFile}`); res.lockFiles = [gemfileLockPath]; const lockedEntries = (0, locked_version_1.extractLockFileEntries)(lockContent); for (const dep of res.deps) { // TODO: types (#22198) const lockedDepValue = lockedEntries.get(`${dep.depName}`); if (lockedDepValue) { dep.lockedVersion = lockedDepValue; } } } } return res; } //# sourceMappingURL=extract.js.map