UNPKG

renovate

Version:

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

198 lines • 7.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.trimAtKey = trimAtKey; exports.expandDepName = expandDepName; exports.extractFromVectors = extractFromVectors; exports.extractVariables = extractVariables; exports.extractPackageFile = extractPackageFile; const array_1 = require("../../../util/array"); const regex_1 = require("../../../util/regex"); const clojure_1 = require("../../datasource/clojure"); function trimAtKey(str, kwName) { const regex = new RegExp(`:${kwName}(?=\\s)`); // TODO #12872 lookahead const keyOffset = str.search(regex); if (keyOffset < 0) { return null; } const withSpaces = str.slice(keyOffset + kwName.length + 1); const valueOffset = withSpaces.search((0, regex_1.regEx)(/[^\s]/)); if (valueOffset < 0) { return null; } return withSpaces.slice(valueOffset); } function expandDepName(name) { return name.includes('/') ? name.replace('/', ':') : `${name}:${name}`; } function extractFromVectors(str, ctx = {}, vars = {}, dimensions = 2) { if (!str.startsWith('[')) { return []; } let balance = 0; const result = []; let idx = 0; let vecPos = 0; let artifactId = ''; let version = ''; // Are we currently parsing a comment? If so, at what depth? let commentLevel = null; const isSpace = (ch) => !!ch && (0, regex_1.regEx)(/[\s,]/).test(ch); const cleanStrLiteral = (s) => s.replace((0, regex_1.regEx)(/^"/), '').replace((0, regex_1.regEx)(/"$/), ''); const yieldDep = () => { if (!commentLevel && artifactId && version) { const depName = expandDepName(cleanStrLiteral(artifactId)); if (version.startsWith('~')) { const varName = version.replace((0, regex_1.regEx)(/^~\s*/), ''); const currentValue = vars[varName]; if (currentValue) { result.push({ ...ctx, datasource: clojure_1.ClojureDatasource.id, depName, currentValue, sharedVariableName: varName, }); } } else { result.push({ ...ctx, datasource: clojure_1.ClojureDatasource.id, depName, currentValue: cleanStrLiteral(version), }); } } artifactId = ''; version = ''; }; let prevChar = null; while (idx < str.length) { const char = str.charAt(idx); if (str.substring(idx).startsWith('#_[')) { commentLevel = balance; } if (char === '[') { balance += 1; if (balance === dimensions) { vecPos = 0; } } else if (char === ']') { balance -= 1; if (commentLevel === balance) { artifactId = ''; version = ''; commentLevel = null; } if (balance === dimensions - 1) { yieldDep(); } if (balance === 0) { break; } } else if (balance === dimensions) { if (isSpace(char)) { if (!isSpace(prevChar)) { vecPos += 1; } } else if (vecPos === 0) { artifactId += char; } else if (vecPos === 1) { version += char; } } prevChar = char; idx += 1; } return result; } function extractLeinRepos(content) { const result = []; const repoContent = trimAtKey(content.replace(/;;.*(?=[\r\n])/g, ''), // get rid of comments // TODO #12872 lookahead 'repositories'); if (repoContent) { let balance = 0; let endIdx = 0; for (let idx = 0; idx < repoContent.length; idx += 1) { const char = repoContent.charAt(idx); if (char === '[') { balance += 1; } else if (char === ']') { balance -= 1; if (balance <= 0) { endIdx = idx; break; } } } const repoSectionContent = repoContent.slice(0, endIdx); const matches = (0, array_1.coerceArray)(repoSectionContent.match((0, regex_1.regEx)(/"https?:\/\/[^"]*"/g))); const urls = matches.map((x) => x.replace((0, regex_1.regEx)(/^"/), '').replace((0, regex_1.regEx)(/"$/), '')); urls.forEach((url) => result.push(url)); } return result; } const defRegex = (0, regex_1.regEx)(/^[\s,]*\([\s,]*def[\s,]+(?<varName>[-+*=<>.!?#$%&_|a-zA-Z][-+*=<>.!?#$%&_|a-zA-Z0-9']+)[\s,]*"(?<stringValue>[^"]*)"[\s,]*\)[\s,]*$/); function extractVariables(content) { const result = {}; const lines = content.split(regex_1.newlineRegex); for (const line of lines) { const match = defRegex.exec(line); if (match?.groups) { const { varName: key, stringValue: val } = match.groups; result[key] = val; } } return result; } function collectDeps(content, key, registryUrls, vars, options = { nested: true, }) { const ctx = { depType: options.depType ?? key, registryUrls, }; // A vector like [["dep-1" "1.0.0"] ["dep-2" "0.0.0"]] is nested // A vector like ["dep-1" "1.0.0"] is not const dimensions = options.nested ? 2 : 1; let result = []; let restContent = trimAtKey(content, key); while (restContent) { result = [ ...result, ...extractFromVectors(restContent, ctx, vars, dimensions), ]; restContent = trimAtKey(restContent, key); } return result; } function extractPackageFile(content) { const registryUrls = extractLeinRepos(content); const vars = extractVariables(content); const deps = [ ...collectDeps(content, 'dependencies', registryUrls, vars), ...collectDeps(content, 'managed-dependencies', registryUrls, vars), ...collectDeps(content, 'plugins', registryUrls, vars), ...collectDeps(content, 'pom-plugins', registryUrls, vars), // 'coords' is used in lein parent, and specifies zero or one // dependencies. These are not wrapped in a vector in the way other // dependencies are. The project.clj fragment looks like // // :parent-project {... :coords ["parent" "version"] ...} // // - https://github.com/achin/lein-parent ...collectDeps(content, 'coords', registryUrls, vars, { nested: false, // The top-level key is 'parent-project', but we skip directly to 'coords'. // So fix the dep type label depType: 'parent-project', }), ]; return { deps }; } //# sourceMappingURL=extract.js.map