UNPKG

renovate

Version:

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

174 lines • 8.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LOCKFIlE_HEADER_TEXT = exports.VERSIONS_LOCK = exports.VERSIONS_PROPS = void 0; exports.usesGcv = usesGcv; exports.isGcvPropsFile = isGcvPropsFile; exports.isGcvLockFile = isGcvLockFile; exports.parseGcv = parseGcv; exports.parseLockFile = parseLockFile; exports.parsePropsFile = parsePropsFile; const tslib_1 = require("tslib"); const logger_1 = require("../../../../logger"); const fs = tslib_1.__importStar(require("../../../../util/fs")); const regex_1 = require("../../../../util/regex"); const string_1 = require("../../../../util/string"); const utils_1 = require("../utils"); exports.VERSIONS_PROPS = 'versions.props'; exports.VERSIONS_LOCK = 'versions.lock'; exports.LOCKFIlE_HEADER_TEXT = (0, regex_1.regEx)(/^# Run \.\/gradlew (?:--write-locks|writeVersionsLock|writeVersionsLocks) to regenerate this file/); /** * Determines if Palantir gradle-consistent-versions is in use, https://github.com/palantir/gradle-consistent-versions. * Both `versions.props` and `versions.lock` must exist and the special header line of lock file must match * * @param versionsPropsFilename is the full file name path of `versions.props` * @param fileContents map with file contents of all files */ function usesGcv(versionsPropsFilename, fileContents) { const versionsLockFile = fs.getSiblingFileName(versionsPropsFilename, exports.VERSIONS_LOCK); return !!fileContents[versionsLockFile]?.match(exports.LOCKFIlE_HEADER_TEXT); } /** * Confirms whether the provided file name is the props file */ function isGcvPropsFile(fileName) { return fileName === exports.VERSIONS_PROPS || fileName.endsWith(`/${exports.VERSIONS_PROPS}`); } /** * Confirms whether the provided file name is the lock file */ function isGcvLockFile(fileName) { return fileName === exports.VERSIONS_LOCK || fileName.endsWith(`/${exports.VERSIONS_LOCK}`); } /** * Parses Gradle-Consistent-Versions files to figure out what dependencies, versions * and groups they contain. The parsing goes like this: * - Parse `versions.props` into deps (or groups) and versions, remembering file offsets * - Parse `versions.lock` into deps and lock-versions * - For each exact dep in props file, lookup the lock-version from lock file * - For each group/regex dep in props file, lookup the set of exact deps and versions in lock file * * @param propsFileName name and path of the props file * @param fileContents text content of all files */ function parseGcv(propsFileName, fileContents) { const propsFileContent = (0, string_1.coerceString)(fileContents[propsFileName]); const lockFileName = fs.getSiblingFileName(propsFileName, exports.VERSIONS_LOCK); const lockFileContent = (0, string_1.coerceString)(fileContents[lockFileName]); const lockFileMap = parseLockFile(lockFileContent); const [propsFileExactMap, propsFileRegexMap] = parsePropsFile(propsFileContent); const extractedDeps = []; // For each exact dep in props file for (const [propDep, versionAndPosition] of propsFileExactMap) { if (lockFileMap.has(propDep)) { const newDep = { managerData: { packageFile: propsFileName, fileReplacePosition: versionAndPosition.filePos, }, depName: propDep, currentValue: versionAndPosition.version, lockedVersion: lockFileMap.get(propDep)?.version, depType: lockFileMap.get(propDep)?.depType, }; extractedDeps.push(newDep); // Remove from the lockfile map so the same exact lib will not be included in globbing lockFileMap.delete(propDep); } } // For each regular expression dep in props file (starting with the longest glob string)... for (const [propDepGlob, propVerAndPos] of propsFileRegexMap) { const globRegex = globToRegex(propDepGlob); for (const [exactDep, lockVersionAndDepType] of lockFileMap) { if (globRegex.test(exactDep)) { const newDep = { managerData: { packageFile: propsFileName, fileReplacePosition: propVerAndPos.filePos, }, depName: exactDep, currentValue: propVerAndPos.version, lockedVersion: lockVersionAndDepType.version, depType: lockVersionAndDepType.depType, sharedVariableName: propDepGlob, }; extractedDeps.push(newDep); // Remove from the lockfile map so the same lib will not be included in more generic globs later lockFileMap.delete(exactDep); } } } return extractedDeps; } // Translate glob syntax to a regex that does the same. Note that we cannot use replaceAll as it does not exist in Node14 // Loosely borrowed mapping to regex from https://github.com/palantir/gradle-consistent-versions/blob/develop/src/main/java/com/palantir/gradle/versions/FuzzyPatternResolver.java function globToRegex(depName) { return (0, regex_1.regEx)(depName .replace(/\*/g, '_WC_CHAR_') .replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&') .replace(/_WC_CHAR_/g, '.*?')); } /** * Parses `versions.lock` */ function parseLockFile(input) { const lockLineRegex = (0, regex_1.regEx)(`^(?<depName>[^:]+:[^:]+):(?<lockVersion>[^ ]+) \\(\\d+ constraints: [0-9a-f]+\\)$`); const depVerMap = new Map(); let isTestDepType = false; for (const line of input.split(regex_1.newlineRegex)) { const lineMatch = lockLineRegex.exec(line); if (lineMatch?.groups) { const { depName, lockVersion } = lineMatch.groups; if ((0, utils_1.isDependencyString)(`${depName}:${lockVersion}`)) { depVerMap.set(depName, { version: lockVersion, depType: isTestDepType ? 'test' : 'dependencies', }); } } else if (line === '[Test dependencies]') { isTestDepType = true; // We know that all lines below this header are test dependencies } } logger_1.logger.trace(`Found ${depVerMap.size} locked dependencies in ${exports.VERSIONS_LOCK}.`); return depVerMap; } /** * Parses `versions.props`, this is CR/LF safe * @param input the entire property file from file system * @return two maps, first being exact matches, second regex matches */ function parsePropsFile(input) { const propsLineRegex = (0, regex_1.regEx)(`^(?<depName>[^:]+:[^=]+?) *= *(?<propsVersion>.*)$`); const depVerExactMap = new Map(); const depVerRegexMap = new Map(); let startOfLineIdx = 0; const isCrLf = input.indexOf('\r\n') > 0; const validGlob = /^[a-zA-Z][-_a-zA-Z0-9.:*]+$/; for (const line of input.split(regex_1.newlineRegex)) { const lineMatch = propsLineRegex.exec(line); if (lineMatch?.groups) { const { depName, propsVersion } = lineMatch.groups; if (validGlob.test(depName) && (0, utils_1.versionLikeSubstring)(propsVersion) !== null) { const startPosInLine = line.lastIndexOf(propsVersion); const propVersionPos = startOfLineIdx + startPosInLine; if (depName.includes('*')) { depVerRegexMap.set(depName, { version: propsVersion, filePos: propVersionPos, }); } else { depVerExactMap.set(depName, { version: propsVersion, filePos: propVersionPos, }); } } } startOfLineIdx += line.length + (isCrLf ? 2 : 1); } logger_1.logger.trace(`Found ${depVerExactMap.size} dependencies and ${depVerRegexMap.size} wildcard dependencies in ${exports.VERSIONS_PROPS}.`); return [depVerExactMap, new Map([...depVerRegexMap].sort().reverse())]; } //# sourceMappingURL=consistent-versions-plugin.js.map