"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.update = exports.lookup = exports.extract = exports.isCacheExtractValid = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const logger_1 = require("../../../logger");
const manager_1 = require("../../../modules/manager");
const repository_1 = require("../../../util/cache/repository");
const check_token_1 = require("../../../util/check-token");
const fingerprint_1 = require("../../../util/fingerprint");
const git_1 = require("../../../util/git");
const extract_1 = require("../extract");
const extract_fingerprint_config_1 = require("../extract/extract-fingerprint-config");
const branchify_1 = require("../updates/branchify");
const deprecated_1 = require("./deprecated");
const fetch_1 = require("./fetch");
const sort_1 = require("./sort");
const write_1 = require("./write");
// istanbul ignore next
function extractStats(packageFiles) {
    if (!packageFiles) {
        return null;
    }
    const stats = {
        managers: {},
        total: {
            fileCount: 0,
            depCount: 0,
        },
    };
    for (const [manager, managerPackageFiles] of Object.entries(packageFiles)) {
        const fileCount = managerPackageFiles.length;
        let depCount = 0;
        for (const file of managerPackageFiles) {
            depCount += file.deps.length;
        }
        stats.managers[manager] = {
            fileCount,
            depCount,
        };
        stats.total.fileCount += fileCount;
        stats.total.depCount += depCount;
    }
    return stats;
}
function isCacheExtractValid(baseBranchSha, configHash, cachedExtract) {
    if (!(cachedExtract?.sha && cachedExtract.configHash)) {
        return false;
    }
    if (cachedExtract.sha !== baseBranchSha) {
        logger_1.logger.debug(`Cached extract result cannot be used due to base branch SHA change (old=${cachedExtract.sha}, new=${baseBranchSha})`);
        return false;
    }
    if (cachedExtract.configHash !== configHash) {
        logger_1.logger.debug('Cached extract result cannot be used due to config change');
        return false;
    }
    if (!cachedExtract.extractionFingerprints) {
        logger_1.logger.debug('Cached extract is missing extractionFingerprints, so cannot be used');
        return false;
    }
    const changedManagers = new Set();
    for (const [manager, fingerprint] of Object.entries(cachedExtract.extractionFingerprints)) {
        if (fingerprint !== manager_1.hashMap.get(manager)) {
            changedManagers.add(manager);
        }
    }
    if (changedManagers.size > 0) {
        logger_1.logger.debug({ changedManagers: [...changedManagers] }, 'Manager fingerprint(s) have changed, extract cache cannot be reused');
        return false;
    }
    logger_1.logger.debug(`Cached extract for sha=${baseBranchSha} is valid and can be used`);
    return true;
}
exports.isCacheExtractValid = isCacheExtractValid;
async function extract(config) {
    logger_1.logger.debug('extract()');
    const { baseBranch } = config;
    const baseBranchSha = (0, git_1.getBranchCommit)(baseBranch);
    let packageFiles;
    const cache = (0, repository_1.getCache)();
    cache.scan || (cache.scan = {});
    const cachedExtract = cache.scan[baseBranch];
    const configHash = (0, fingerprint_1.fingerprint)((0, extract_fingerprint_config_1.generateFingerprintConfig)(config));
    // istanbul ignore if
    if (isCacheExtractValid(baseBranchSha, configHash, cachedExtract)) {
        packageFiles = cachedExtract.packageFiles;
        try {
            for (const files of Object.values(packageFiles)) {
                for (const file of files) {
                    for (const dep of file.deps) {
                        delete dep.updates;
                    }
                }
            }
            logger_1.logger.debug('Deleted cached dep updates');
        }
        catch (err) {
            logger_1.logger.info({ err }, 'Error deleting cached dep updates');
        }
    }
    else {
        await (0, git_1.checkoutBranch)(baseBranch);
        const extractResult = (await (0, extract_1.extractAllDependencies)(config)) || {};
        packageFiles = extractResult.packageFiles;
        const { extractionFingerprints } = extractResult;
        // TODO: fix types (#7154)
        cache.scan[baseBranch] = {
            sha: baseBranchSha,
            configHash,
            extractionFingerprints,
            packageFiles,
        };
        // Clean up cached branch extracts
        const baseBranches = is_1.default.nonEmptyArray(config.baseBranches)
            ? config.baseBranches
            : [baseBranch];
        Object.keys(cache.scan).forEach((branchName) => {
            if (!baseBranches.includes(branchName)) {
                delete cache.scan[branchName];
            }
        });
    }
    const stats = extractStats(packageFiles);
    logger_1.logger.info({ baseBranch: config.baseBranch, stats }, `Dependency extraction complete`);
    logger_1.logger.trace({ config: packageFiles }, 'packageFiles');
    (0, check_token_1.checkGithubToken)(packageFiles);
    return packageFiles;
}
exports.extract = extract;
async function lookup(config, packageFiles) {
    await (0, fetch_1.fetchUpdates)(config, packageFiles);
    await (0, deprecated_1.raiseDeprecationWarnings)(config, packageFiles);
    const { branches, branchList } = await (0, branchify_1.branchifyUpgrades)(config, packageFiles);
    logger_1.logger.debug({ baseBranch: config.baseBranch, config: packageFiles }, 'packageFiles with updates');
    (0, sort_1.sortBranches)(branches);
    return { branches, branchList, packageFiles };
}
exports.lookup = lookup;
async function update(config, branches) {
    let res;
    // istanbul ignore else
    if (config.repoIsOnboarded) {
        res = await (0, write_1.writeUpdates)(config, branches);
    }
    return res;
}
exports.update = update;
//# sourceMappingURL=extract-update.js.map