"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateArtifacts = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const shlex_1 = require("shlex");
const upath_1 = require("upath");
const error_messages_1 = require("../../../constants/error-messages");
const logger_1 = require("../../../logger");
const exec_1 = require("../../../util/exec");
const fs_1 = require("../../../util/fs");
const git_1 = require("../../../util/git");
const regex_1 = require("../../../util/regex");
const utils_1 = require("../gradle-wrapper/utils");
const consistent_versions_plugin_1 = require("./extract/consistent-versions-plugin");
const utils_2 = require("./utils");
// .lockfile is gradle default lockfile, /versions.lock is gradle-consistent-versions plugin lockfile
function isLockFile(fileName) {
    return fileName.endsWith('.lockfile') || (0, consistent_versions_plugin_1.isGcvLockFile)(fileName);
}
async function getUpdatedLockfiles(oldLockFileContentMap) {
    const res = [];
    const status = await (0, git_1.getRepoStatus)();
    for (const modifiedFile of status.modified) {
        if (isLockFile(modifiedFile)) {
            const newContent = await (0, fs_1.readLocalFile)(modifiedFile, 'utf8');
            if (oldLockFileContentMap[modifiedFile] !== newContent) {
                res.push({
                    file: {
                        type: 'addition',
                        path: modifiedFile,
                        contents: newContent,
                    },
                });
            }
        }
    }
    return res;
}
async function getSubProjectList(cmd, execOptions) {
    const subprojects = ['']; // = root project
    const subprojectsRegex = (0, regex_1.regEx)(/^[ \t]*subprojects: \[(?<subprojects>.+)\]/m);
    const gradleProperties = await (0, exec_1.exec)(`${cmd} properties`, execOptions);
    const subprojectsMatch = gradleProperties.stdout.match(subprojectsRegex);
    if (subprojectsMatch?.groups?.subprojects) {
        const projectRegex = (0, regex_1.regEx)(/project '(?<name>.+?)'/g);
        const matches = subprojectsMatch.groups.subprojects.matchAll(projectRegex);
        for (const match of matches) {
            if (match?.groups?.name) {
                subprojects.push(match.groups.name);
            }
        }
    }
    return subprojects;
}
async function getGradleVersion(gradlewFile) {
    const propertiesFile = (0, upath_1.join)((0, upath_1.dirname)(gradlewFile), 'gradle/wrapper/gradle-wrapper.properties');
    const properties = await (0, fs_1.readLocalFile)(propertiesFile, 'utf8');
    const extractResult = (0, utils_1.extractGradleVersion)(properties ?? '');
    return extractResult ? extractResult.version : null;
}
async function updateArtifacts({ packageFileName, updatedDeps, newPackageFileContent, config, }) {
    logger_1.logger.debug(`gradle.updateArtifacts(${packageFileName})`);
    const fileList = await (0, git_1.getFileList)();
    const lockFiles = fileList.filter((file) => isLockFile(file));
    if (!lockFiles.length) {
        logger_1.logger.debug('No Gradle dependency lockfiles found - skipping update');
        return null;
    }
    const gradlewName = (0, utils_1.gradleWrapperFileName)();
    const gradlewFile = await (0, fs_1.findUpLocal)(gradlewName, (0, upath_1.dirname)(packageFileName));
    if (!gradlewFile) {
        logger_1.logger.debug('Found Gradle dependency lockfiles but no gradlew - aborting update');
        return null;
    }
    if (config.isLockFileMaintenance &&
        (!(0, utils_2.isGradleBuildFile)(packageFileName) ||
            (0, upath_1.dirname)(packageFileName) !== (0, upath_1.dirname)(gradlewFile))) {
        logger_1.logger.trace('No build.gradle(.kts) file or not in root project - skipping lock file maintenance');
        return null;
    }
    logger_1.logger.debug('Updating found Gradle dependency lockfiles');
    try {
        const oldLockFileContentMap = await (0, fs_1.getFileContentMap)(lockFiles);
        await (0, fs_1.writeLocalFile)(packageFileName, newPackageFileContent);
        await (0, utils_1.prepareGradleCommand)(gradlewFile);
        let cmd = `${gradlewName} --console=plain -q`;
        const execOptions = {
            cwdFile: gradlewFile,
            docker: {},
            extraEnv: utils_1.extraEnv,
            toolConstraints: [
                {
                    toolName: 'java',
                    constraint: config.constraints?.java ??
                        (0, utils_1.getJavaConstraint)(await getGradleVersion(gradlewFile)),
                },
            ],
        };
        const subprojects = await getSubProjectList(cmd, execOptions);
        cmd += ` ${subprojects
            .map((project) => project + ':dependencies')
            .map(shlex_1.quote)
            .join(' ')}`;
        if (config.isLockFileMaintenance || (0, consistent_versions_plugin_1.isGcvPropsFile)(packageFileName)) {
            cmd += ' --write-locks';
        }
        else {
            const updatedDepNames = updatedDeps
                .map(({ depName, packageName }) => packageName ?? depName)
                .filter(is_1.default.nonEmptyStringAndNotWhitespace);
            cmd += ` --update-locks ${updatedDepNames.map(shlex_1.quote).join(',')}`;
        }
        await (0, exec_1.exec)(cmd, execOptions);
        const res = await getUpdatedLockfiles(oldLockFileContentMap);
        logger_1.logger.debug('Returning updated Gradle dependency lockfiles');
        return res.length > 0 ? res : null;
    }
    catch (err) {
        if (err.message === error_messages_1.TEMPORARY_ERROR) {
            throw err;
        }
        logger_1.logger.debug({ err }, 'Error while updating Gradle dependency lockfiles');
        return [
            {
                artifactError: {
                    lockFile: packageFileName,
                    stderr: err.message,
                },
            },
        ];
    }
}
exports.updateArtifacts = updateArtifacts;
//# sourceMappingURL=artifacts.js.map