"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateArtifacts = void 0;
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 config_formatter_1 = require("./config-formatter");
const package_tree_1 = require("./package-tree");
const util_1 = require("./util");
async function createCachedNuGetConfigFile(nugetCacheDir, packageFileName) {
    const registries = (await (0, util_1.getConfiguredRegistries)(packageFileName)) ?? (0, util_1.getDefaultRegistries)();
    const contents = (0, config_formatter_1.createNuGetConfigXml)(registries);
    const cachedNugetConfigFile = (0, upath_1.join)(nugetCacheDir, `nuget.config`);
    await (0, fs_1.ensureDir)(nugetCacheDir);
    await (0, fs_1.outputCacheFile)(cachedNugetConfigFile, contents);
    return cachedNugetConfigFile;
}
async function runDotnetRestore(packageFileName, dependentPackageFileNames, config) {
    const nugetCacheDir = (0, upath_1.join)((0, fs_1.privateCacheDir)(), 'nuget');
    const nugetConfigFile = await createCachedNuGetConfigFile(nugetCacheDir, packageFileName);
    const execOptions = {
        docker: {},
        userConfiguredEnv: config.env,
        extraEnv: {
            NUGET_PACKAGES: (0, upath_1.join)(nugetCacheDir, 'packages'),
            MSBUILDDISABLENODEREUSE: '1',
        },
        toolConstraints: [
            { toolName: 'dotnet', constraint: config.constraints?.dotnet },
        ],
    };
    const cmds = [
        ...dependentPackageFileNames.map((fileName) => `dotnet restore ${(0, shlex_1.quote)(fileName)} --force-evaluate --configfile ${(0, shlex_1.quote)(nugetConfigFile)}`),
    ];
    await (0, exec_1.exec)(cmds, execOptions);
}
async function updateArtifacts({ packageFileName, newPackageFileContent, config, updatedDeps, }) {
    logger_1.logger.debug(`nuget.updateArtifacts(${packageFileName})`);
    // https://github.com/NuGet/Home/wiki/Centrally-managing-NuGet-package-versions
    // https://github.com/microsoft/MSBuildSdks/tree/main/src/CentralPackageVersions
    const isCentralManament = packageFileName === package_tree_1.NUGET_CENTRAL_FILE ||
        packageFileName === package_tree_1.MSBUILD_CENTRAL_FILE ||
        packageFileName.endsWith(`/${package_tree_1.NUGET_CENTRAL_FILE}`) ||
        packageFileName.endsWith(`/${package_tree_1.MSBUILD_CENTRAL_FILE}`);
    if (!isCentralManament &&
        !(0, regex_1.regEx)(/(?:cs|vb|fs)proj$/i).test(packageFileName)) {
        // This could be implemented in the future if necessary.
        // It's not that easy though because the questions which
        // project file to restore how to determine which lock files
        // have been changed in such cases.
        logger_1.logger.debug({ packageFileName }, 'Not updating lock file for non project files');
        return null;
    }
    const deps = await (0, package_tree_1.getDependentPackageFiles)(packageFileName, isCentralManament);
    const packageFiles = deps.filter((d) => d.isLeaf).map((d) => d.name);
    logger_1.logger.trace({ packageFiles }, `Found ${packageFiles.length} dependent package files`);
    const lockFileNames = deps.map((f) => (0, fs_1.getSiblingFileName)(f.name, 'packages.lock.json'));
    const existingLockFileContentMap = await (0, git_1.getFiles)(lockFileNames);
    const hasLockFileContent = Object.values(existingLockFileContentMap).some((val) => !!val);
    if (!hasLockFileContent) {
        logger_1.logger.debug({ packageFileName }, 'No lock file found for package or dependents');
        return null;
    }
    try {
        if (updatedDeps.length === 0 && config.isLockFileMaintenance !== true) {
            logger_1.logger.debug(`Not updating lock file because no deps changed and no lock file maintenance.`);
            return null;
        }
        await (0, fs_1.writeLocalFile)(packageFileName, newPackageFileContent);
        await runDotnetRestore(packageFileName, packageFiles, config);
        const newLockFileContentMap = await (0, fs_1.getLocalFiles)(lockFileNames);
        const retArray = [];
        for (const lockFileName of lockFileNames) {
            if (existingLockFileContentMap[lockFileName] ===
                newLockFileContentMap[lockFileName]) {
                logger_1.logger.trace(`Lock file ${lockFileName} is unchanged`);
            }
            else if (newLockFileContentMap[lockFileName]) {
                retArray.push({
                    file: {
                        type: 'addition',
                        path: lockFileName,
                        contents: newLockFileContentMap[lockFileName],
                    },
                });
            }
            // TODO: else should we return an artifact error if new content is missing?
        }
        return retArray.length > 0 ? retArray : null;
    }
    catch (err) {
        // istanbul ignore if
        if (err.message === error_messages_1.TEMPORARY_ERROR) {
            throw err;
        }
        logger_1.logger.debug({ err }, 'Failed to generate lock file');
        return [
            {
                artifactError: {
                    lockFile: lockFileNames.join(', '),
                    // error is written to stdout
                    stderr: err.stdout || err.message,
                },
            },
        ];
    }
}
exports.updateArtifacts = updateArtifacts;
//# sourceMappingURL=artifacts.js.map