renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
156 lines • 6.01 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.extrasPattern = exports.packagePattern = void 0;
exports.extractPackageFile = extractPackageFile;
const tslib_1 = require("tslib");
const detect_tools_1 = require("@renovatebot/detect-tools");
const pep440_1 = require("@renovatebot/pep440");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const logger_1 = require("../../../logger");
const fs_1 = require("../../../util/fs");
const util_1 = require("../../../util/fs/util");
const regex_1 = require("../../../util/regex");
const toml_1 = require("../../../util/toml");
const pypi_1 = require("../../datasource/pypi");
const common_1 = require("../../datasource/pypi/common");
// based on https://www.python.org/dev/peps/pep-0508/#names
exports.packagePattern = '[A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9]';
exports.extrasPattern = '(?:\\s*\\[[^\\]]+\\])*';
const packageRegex = (0, regex_1.regEx)(`^(${exports.packagePattern})(${exports.extrasPattern})$`, 'i');
const rangePattern = pep440_1.RANGE_PATTERN;
const specifierPartPattern = `\\s*${rangePattern.replace((0, regex_1.regEx)(/\?<\w+>/g), '?:')}\\s*`;
const specifierPattern = `${specifierPartPattern}(?:,${specifierPartPattern})*`;
const specifierRegex = (0, regex_1.regEx)(`^${specifierPattern}$`);
function extractFromSection(sectionName, pipfileSection, sources) {
const deps = Object.entries(pipfileSection)
.map((x) => {
const [packageNameString, requirements] = x;
let depName = packageNameString;
let currentValue;
let nestedVersion = false;
let skipReason;
if (is_1.default.object(requirements)) {
if (requirements.git) {
skipReason = 'git-dependency';
}
else if (requirements.file) {
skipReason = 'file-dependency';
}
else if (requirements.path) {
skipReason = 'local-dependency';
}
else if (requirements.version) {
currentValue = requirements.version;
nestedVersion = true;
}
else {
skipReason = 'unspecified-version';
}
}
else {
currentValue = requirements;
}
if (currentValue === '*') {
skipReason = 'unspecified-version';
}
if (!skipReason) {
const packageMatches = packageRegex.exec(packageNameString);
if (packageMatches) {
depName = packageMatches[1];
}
else {
logger_1.logger.debug(`Skipping dependency with malformed package name "${packageNameString}".`);
skipReason = 'invalid-name';
}
// validated above
const specifierMatches = specifierRegex.exec(currentValue);
if (!specifierMatches) {
logger_1.logger.debug(`Skipping dependency with malformed version specifier "${currentValue}".`);
skipReason = 'invalid-version';
}
}
const dep = {
depType: sectionName,
depName,
packageName: (0, common_1.normalizePythonDepName)(depName),
managerData: {},
};
if (currentValue) {
dep.currentValue = currentValue;
}
if (skipReason) {
dep.skipReason = skipReason;
}
else {
dep.datasource = pypi_1.PypiDatasource.id;
}
if (!skipReason && currentValue?.startsWith('==')) {
dep.currentVersion = currentValue.replace((0, regex_1.regEx)(/^==\s*/), '');
}
if (nestedVersion) {
// TODO #22198
dep.managerData.nestedVersion = nestedVersion;
}
if (sources && is_1.default.object(requirements) && requirements.index) {
const source = sources.find((item) => item.name === requirements.index);
if (source) {
dep.registryUrls = [source.url];
}
}
return dep;
})
.filter(Boolean);
return deps;
}
function isPipRequirements(section) {
return (!is_1.default.array(section) &&
is_1.default.object(section) &&
!Object.values(section).some((dep) => !is_1.default.object(dep) && !is_1.default.string(dep)));
}
async function extractPackageFile(content, packageFile) {
logger_1.logger.trace(`pipenv.extractPackageFile(${packageFile})`);
let pipfile;
try {
// TODO: fix type (#9610)
pipfile = (0, toml_1.parse)(content);
}
catch (err) {
logger_1.logger.debug({ err, packageFile }, 'Error parsing Pipfile');
return null;
}
const res = { deps: [] };
const sources = pipfile?.source;
if (sources) {
res.registryUrls = sources.map((source) => source.url);
}
res.deps = Object.entries(pipfile)
.map(([category, section]) => {
if (category === 'source' ||
category === 'requires' ||
!isPipRequirements(section)) {
return [];
}
return extractFromSection(category, section, sources);
})
.flat();
if (!res.deps.length) {
return null;
}
const extractedConstraints = {};
const pipfileDir = (0, fs_1.getParentDir)((0, util_1.ensureLocalPath)(packageFile));
const pythonConstraint = await detect_tools_1.pipenv.getPythonConstraint(pipfileDir);
if (pythonConstraint) {
extractedConstraints.python = pythonConstraint;
}
const pipenvConstraint = await detect_tools_1.pipenv.getPipenvConstraint(pipfileDir);
if (pipenvConstraint) {
extractedConstraints.pipenv = pipenvConstraint;
}
const lockFileName = `${packageFile}.lock`;
if (await (0, fs_1.localPathExists)(lockFileName)) {
res.lockFiles = [lockFileName];
}
res.extractedConstraints = extractedConstraints;
return res;
}
//# sourceMappingURL=extract.js.map