renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
254 lines • 12.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.confirmIfDepUpdated = confirmIfDepUpdated;
exports.checkBranchDepsMatchBaseDeps = checkBranchDepsMatchBaseDeps;
exports.doAutoReplace = doAutoReplace;
const tslib_1 = require("tslib");
// TODO #22198
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const error_messages_1 = require("../../../../constants/error-messages");
const logger_1 = require("../../../../logger");
const manager_1 = require("../../../../modules/manager");
const fs_1 = require("../../../../util/fs");
const regex_1 = require("../../../../util/regex");
const string_1 = require("../../../../util/string");
const template_1 = require("../../../../util/template");
async function confirmIfDepUpdated(upgrade, newContent) {
const { manager, packageFile, depIndex } = upgrade;
let newUpgrade;
try {
const newExtract = await (0, manager_1.extractPackageFile)(manager, newContent, packageFile, upgrade);
// istanbul ignore if
if (!newExtract) {
// TODO: fix types (#22198)
logger_1.logger.debug(`Could not extract ${packageFile} (manager=${manager}) after autoreplace. Did the autoreplace make the file unparseable?`);
logger_1.logger.trace({ packageFile, content: newContent }, 'packageFile content after autoreplace');
return false;
}
// istanbul ignore if
if (!newExtract.deps?.length) {
logger_1.logger.debug(`Extracted ${packageFile} after autoreplace has no deps array. Did the autoreplace make the file unparseable?`);
return false;
}
// istanbul ignore if
if (is_1.default.number(depIndex) && depIndex >= newExtract.deps.length) {
logger_1.logger.debug(`Extracted ${packageFile} after autoreplace has fewer deps than expected.`);
return false;
}
newUpgrade = newExtract.deps[depIndex];
}
catch (err) /* istanbul ignore next */ {
logger_1.logger.debug({ manager, packageFile, err }, 'Failed to parse newContent');
}
if (!newUpgrade) {
logger_1.logger.debug(`No newUpgrade in ${packageFile}`);
return false;
}
if (upgrade.depName !== newUpgrade.depName &&
upgrade.newName !== newUpgrade.depName) {
logger_1.logger.debug({
manager,
packageFile,
currentDepName: upgrade.depName,
newDepName: newUpgrade.depName,
}, 'depName mismatch');
return false;
}
if (upgrade.newName && upgrade.newName !== newUpgrade.depName) {
logger_1.logger.debug({
manager,
packageFile,
currentDepName: upgrade.depName,
newDepName: newUpgrade.depName,
}, 'depName is not updated');
return false;
}
if (upgrade.newValue && upgrade.newValue !== newUpgrade.currentValue) {
logger_1.logger.debug({
depName: upgrade.depName,
manager,
packageFile,
expectedValue: upgrade.newValue,
foundValue: newUpgrade.currentValue,
}, 'Value is not updated');
return false;
}
if (upgrade.newDigest &&
(upgrade.isPinDigest === true || upgrade.currentDigest) &&
upgrade.newDigest !== newUpgrade.currentDigest) {
logger_1.logger.debug({
depName: upgrade.depName,
manager,
packageFile,
expectedValue: upgrade.newDigest,
foundValue: newUpgrade.currentDigest,
}, 'Digest is not updated');
return false;
}
return true;
}
function getDepsSignature(deps) {
// TODO: types (#22198)
return deps
.map((dep) => `${(dep.depName ?? dep.packageName)}${(dep.packageName ??
dep.depName)}`)
.join(',');
}
async function checkBranchDepsMatchBaseDeps(upgrade, branchContent) {
const { baseDeps, manager, packageFile } = upgrade;
try {
const res = await (0, manager_1.extractPackageFile)(manager, branchContent, packageFile, upgrade);
const branchDeps = res.deps;
return getDepsSignature(baseDeps) === getDepsSignature(branchDeps);
}
catch /* istanbul ignore next */ {
logger_1.logger.info({ manager, packageFile }, 'Failed to parse branchContent - rebasing');
return false;
}
}
async function checkExistingBranch(upgrade, existingContent) {
const { packageFile, depName } = upgrade;
if (!(await checkBranchDepsMatchBaseDeps(upgrade, existingContent))) {
logger_1.logger.debug({ packageFile, depName }, 'Rebasing branch after deps list has changed');
return null;
}
if (!(await confirmIfDepUpdated(upgrade, existingContent))) {
logger_1.logger.debug({ packageFile, depName }, 'Rebasing after outdated branch dep found');
return null;
}
// TODO: fix types (#22198)
logger_1.logger.debug(`Branch dep ${depName} in ${packageFile} is already updated`);
return existingContent;
}
async function doAutoReplace(upgrade, existingContent, reuseExistingBranch, firstUpdate = true) {
const { packageFile, depName, depNameTemplate, newName, currentValue, currentValueTemplate, newValue, currentDigest, currentDigestShort, newDigest, autoReplaceGlobalMatch, autoReplaceStringTemplate, } = upgrade;
/*
If replacement support for more managers is added,
please also update the list in docs/usage/configuration-options.md
at replacementName and replacementVersion
*/
if (reuseExistingBranch) {
return await checkExistingBranch(upgrade, existingContent);
}
const replaceWithoutReplaceString = is_1.default.string(newName) &&
newName !== depName &&
(is_1.default.undefined(upgrade.replaceString) ||
!upgrade.replaceString?.includes(depName));
const replaceString = upgrade.replaceString ?? currentValue ?? currentDigest;
logger_1.logger.trace({ depName, replaceString }, 'autoReplace replaceString');
let searchIndex;
if (replaceWithoutReplaceString) {
const depIndex = existingContent.indexOf(depName);
const valIndex = existingContent.indexOf(currentValue);
searchIndex = depIndex < valIndex ? depIndex : valIndex;
}
else {
searchIndex = existingContent.indexOf(replaceString);
}
if (searchIndex === -1) {
logger_1.logger.info({ packageFile, depName, existingContent, replaceString }, 'Cannot find replaceString in current file content. Was it already updated?');
return existingContent;
}
try {
let newString;
if (autoReplaceStringTemplate && !newName) {
newString = (0, template_1.compile)(autoReplaceStringTemplate, upgrade, false);
}
else {
newString = replaceString;
const autoReplaceRegExpFlag = autoReplaceGlobalMatch ? 'g' : '';
if (currentValue && newValue && currentValue !== newValue) {
if (!newString.includes(currentValue)) {
logger_1.logger.debug({ stringToReplace: newString, currentValue, currentValueTemplate }, 'currentValue not found in string to replace');
}
newString = newString.replace((0, regex_1.regEx)((0, regex_1.escapeRegExp)(currentValue), autoReplaceRegExpFlag), newValue);
}
if (depName && newName && depName !== newName) {
if (!newString.includes(depName)) {
logger_1.logger.debug({ stringToReplace: newString, depName, depNameTemplate }, 'depName not found in string to replace');
}
newString = newString.replace((0, regex_1.regEx)((0, regex_1.escapeRegExp)(depName), autoReplaceRegExpFlag), newName);
}
if (currentDigest && newDigest && currentDigest !== newDigest) {
if (!newString.includes(currentDigest)) {
logger_1.logger.debug({ stringToReplace: newString, currentDigest }, 'currentDigest not found in string to replace');
}
newString = newString.replace((0, regex_1.regEx)((0, regex_1.escapeRegExp)(currentDigest), autoReplaceRegExpFlag), newDigest);
}
else if (currentDigestShort &&
newDigest &&
currentDigestShort !== newDigest) {
if (!newString.includes(currentDigestShort)) {
logger_1.logger.debug({ stringToReplace: newString, currentDigestShort }, 'currentDigestShort not found in string to replace');
}
newString = newString.replace((0, regex_1.regEx)((0, regex_1.escapeRegExp)(currentDigestShort), autoReplaceRegExpFlag), newDigest);
}
}
if (!firstUpdate && (await confirmIfDepUpdated(upgrade, existingContent))) {
logger_1.logger.debug({ packageFile, depName }, 'Package file is already updated - no work to do');
return existingContent;
}
logger_1.logger.debug({ packageFile, depName }, `Starting search at index ${searchIndex}`);
let newContent = existingContent;
let nameReplaced = !newName;
let valueReplaced = !newValue;
let startIndex = searchIndex;
// Iterate through the rest of the file
for (; searchIndex < newContent.length; searchIndex += 1) {
// First check if we have a hit for the old version
if (replaceWithoutReplaceString) {
// look for depName and currentValue
if (newName && (0, string_1.matchAt)(newContent, searchIndex, depName)) {
logger_1.logger.debug({ packageFile, depName }, `Found depName at index ${searchIndex}`);
if (nameReplaced) {
startIndex += 1;
searchIndex = startIndex;
await (0, fs_1.writeLocalFile)(upgrade.packageFile, existingContent);
newContent = existingContent;
nameReplaced = false;
valueReplaced = false;
continue;
}
// replace with newName
newContent = (0, string_1.replaceAt)(newContent, searchIndex, depName, newName);
await (0, fs_1.writeLocalFile)(upgrade.packageFile, newContent);
nameReplaced = true;
}
else if (newValue &&
(0, string_1.matchAt)(newContent, searchIndex, currentValue)) {
logger_1.logger.debug({ packageFile, currentValue }, `Found currentValue at index ${searchIndex}`);
// Now test if the result matches
newContent = (0, string_1.replaceAt)(newContent, searchIndex, currentValue, newValue);
await (0, fs_1.writeLocalFile)(upgrade.packageFile, newContent);
valueReplaced = true;
}
if (nameReplaced && valueReplaced) {
if (await confirmIfDepUpdated(upgrade, newContent)) {
return newContent;
}
await (0, fs_1.writeLocalFile)(upgrade.packageFile, existingContent);
newContent = existingContent;
nameReplaced = false;
valueReplaced = false;
}
}
else if ((0, string_1.matchAt)(newContent, searchIndex, replaceString)) {
logger_1.logger.debug({ packageFile, depName }, `Found match at index ${searchIndex}`);
// Now test if the result matches
newContent = (0, string_1.replaceAt)(newContent, searchIndex, replaceString, newString);
await (0, fs_1.writeLocalFile)(upgrade.packageFile, newContent);
if (await confirmIfDepUpdated(upgrade, newContent)) {
return newContent;
}
await (0, fs_1.writeLocalFile)(upgrade.packageFile, existingContent);
newContent = existingContent;
}
}
}
catch (err) /* istanbul ignore next */ {
logger_1.logger.debug({ packageFile, depName, err }, 'doAutoReplace error');
}
// istanbul ignore next
throw new Error(error_messages_1.WORKER_FILE_UPDATE_FAILED);
}
//# sourceMappingURL=auto-replace.js.map