"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectImpactGraphGenerator = void 0;
const js_yaml_1 = __importDefault(require("js-yaml"));
const node_core_library_1 = require("@rushstack/node-core-library");
const terminal_1 = require("@rushstack/terminal");
const Stopwatch_1 = require("../utilities/Stopwatch");
const RushConstants_1 = require("./RushConstants");
/**
 * Default global excluded globs
 * Only used if the `<repository_root>/.mergequeueignore` does not exist
 */
const DEFAULT_GLOBAL_EXCLUDED_GLOBS = ['common/autoinstallers/**'];
async function tryReadFileLinesAsync(filePath) {
    let fileContents;
    try {
        fileContents = await node_core_library_1.FileSystem.readFileAsync(filePath);
    }
    catch (error) {
        if (!node_core_library_1.FileSystem.isNotExistError(error)) {
            throw error;
        }
    }
    if (fileContents) {
        return node_core_library_1.Text.convertToLf(fileContents).split('\n');
    }
}
class ProjectImpactGraphGenerator {
    /**
     * Get repositoryRoot and load projects within the rush.json
     */
    constructor(terminal, rushConfiguration) {
        this._terminal = terminal;
        this._rushConfiguration = rushConfiguration;
        const { rushJsonFolder } = rushConfiguration;
        this._repositoryRoot = rushJsonFolder;
        this._projectImpactGraphFilePath = `${rushJsonFolder}/${RushConstants_1.RushConstants.projectImpactGraphFilename}`;
    }
    /**
     * Load global excluded globs
     */
    async _loadGlobalExcludedGlobsAsync() {
        const filePath = `${this._repositoryRoot}/${RushConstants_1.RushConstants.mergeQueueIgnoreFileName}`;
        return await tryReadFileLinesAsync(filePath);
    }
    /**
     * Load project excluded globs
     * @param projectRootRelativePath - project root relative path
     */
    async _tryLoadProjectExcludedGlobsAsync(projectRootRelativePath) {
        const filePath = `${this._repositoryRoot}/${projectRootRelativePath}/${RushConstants_1.RushConstants.mergeQueueIgnoreFileName}`;
        const globs = await tryReadFileLinesAsync(filePath);
        if (globs) {
            for (let i = 0; i < globs.length; i++) {
                globs[i] = `${projectRootRelativePath}/${globs[i]}`;
            }
            return globs;
        }
    }
    /**
     * Core Logic: generate project-impact-graph.yaml
     */
    async generateAsync() {
        const stopwatch = Stopwatch_1.Stopwatch.start();
        const [globalExcludedGlobs = DEFAULT_GLOBAL_EXCLUDED_GLOBS, projectEntries] = await Promise.all([
            this._loadGlobalExcludedGlobsAsync(),
            node_core_library_1.Async.mapAsync(this._rushConfiguration.projects, async ({ packageName, consumingProjects, projectRelativeFolder }) => {
                const dependentList = [packageName];
                for (const consumingProject of consumingProjects) {
                    dependentList.push(consumingProject.packageName);
                }
                const projectImpactGraphProjectConfiguration = {
                    includedGlobs: [`${projectRelativeFolder}/**`],
                    dependentProjects: dependentList.sort()
                };
                const projectExcludedGlobs = await this._tryLoadProjectExcludedGlobsAsync(projectRelativeFolder);
                if (projectExcludedGlobs) {
                    projectImpactGraphProjectConfiguration.excludedGlobs = projectExcludedGlobs;
                }
                return [packageName, projectImpactGraphProjectConfiguration];
            }, { concurrency: 50 })
        ]);
        projectEntries.sort(([aName], [bName]) => aName.localeCompare(bName));
        const projects = Object.fromEntries(projectEntries);
        const content = { globalExcludedGlobs, projects };
        await node_core_library_1.FileSystem.writeFileAsync(this._projectImpactGraphFilePath, js_yaml_1.default.dump(content));
        stopwatch.stop();
        this._terminal.writeLine();
        this._terminal.writeLine(terminal_1.Colorize.green(`Generate project impact graph successfully. (${stopwatch.toString()})`));
    }
    async validateAsync() {
        // TODO: More validation other than just existence
        return await node_core_library_1.FileSystem.existsAsync(this._projectImpactGraphFilePath);
    }
}
exports.ProjectImpactGraphGenerator = ProjectImpactGraphGenerator;
//# sourceMappingURL=ProjectImpactGraphGenerator.js.map