"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateAtomizedTasks = exports.makeAcyclic = exports.findCycle = void 0;
const path_1 = require("path");
const output_1 = require("../utils/output");
const fs_1 = require("fs");
const fs_extra_1 = require("fs-extra");
const workspace_root_1 = require("../utils/workspace-root");
const nx_cloud_utils_1 = require("../utils/nx-cloud-utils");
const configuration_1 = require("../config/configuration");
function _findCycle(graph, id, visited, path) {
    if (visited[id])
        return null;
    visited[id] = true;
    for (const d of graph.dependencies[id]) {
        if (path.includes(d))
            return [...path, d];
        const cycle = _findCycle(graph, d, visited, [...path, d]);
        if (cycle)
            return cycle;
    }
    return null;
}
function findCycle(graph) {
    const visited = {};
    for (const t of Object.keys(graph.dependencies)) {
        visited[t] = false;
    }
    for (const t of Object.keys(graph.dependencies)) {
        const cycle = _findCycle(graph, t, visited, [t]);
        if (cycle)
            return cycle;
    }
    return null;
}
exports.findCycle = findCycle;
function _makeAcyclic(graph, id, visited, path) {
    if (visited[id])
        return;
    visited[id] = true;
    const deps = graph.dependencies[id];
    for (const d of [...deps]) {
        if (path.includes(d)) {
            deps.splice(deps.indexOf(d), 1);
        }
        else {
            _makeAcyclic(graph, d, visited, [...path, d]);
        }
    }
    return null;
}
function makeAcyclic(graph) {
    const visited = {};
    for (const t of Object.keys(graph.dependencies)) {
        visited[t] = false;
    }
    for (const t of Object.keys(graph.dependencies)) {
        _makeAcyclic(graph, t, visited, [t]);
    }
    graph.roots = Object.keys(graph.dependencies).filter((t) => graph.dependencies[t].length === 0);
}
exports.makeAcyclic = makeAcyclic;
function validateAtomizedTasks(taskGraph, projectGraph) {
    if (process.env['NX_SKIP_ATOMIZER_VALIDATION']) {
        return;
    }
    const getNonAtomizedTargetForTask = (task) => projectGraph.nodes[task.target.project]?.data?.targets?.[task.target.target]
        ?.metadata?.nonAtomizedTarget;
    const tasksWithAtomizer = Object.values(taskGraph.tasks).filter((task) => getNonAtomizedTargetForTask(task) !== undefined);
    if (tasksWithAtomizer.length > 0 && !isInDTE()) {
        const usingNxCloud = (0, nx_cloud_utils_1.isNxCloudUsed)((0, configuration_1.readNxJson)());
        const nonAtomizedTasks = tasksWithAtomizer
            .map((t) => getNonAtomizedTargetForTask(t))
            .filter((item, index, arr) => arr.indexOf(item) === index);
        const moreInfoLines = [
            `Please enable ${usingNxCloud ? 'distribution with Nx Agents' : 'Nx Cloud'} or use the slower ${nonAtomizedTasks.join('/')} task${nonAtomizedTasks.length > 1 ? 's' : ''}.`,
            'Learn more at https://nx.dev/ci/features/split-e2e-tasks#use-atomizer-only-with-nx-cloud-distribution',
        ];
        if (tasksWithAtomizer.length === 1) {
            output_1.output.error({
                title: `The ${tasksWithAtomizer[0].id} task uses the atomizer and should only be run with ${usingNxCloud ? 'distribution' : 'Nx Cloud'}.`,
                bodyLines: [...moreInfoLines],
            });
        }
        else {
            output_1.output.error({
                title: `The following tasks use the atomizer and should only be run with ${usingNxCloud ? 'distribution' : 'Nx Cloud'}:`,
                bodyLines: [
                    `${tasksWithAtomizer.map((task) => task.id).join(', ')}`,
                    ...moreInfoLines,
                ],
            });
        }
        process.exit(1);
    }
}
exports.validateAtomizedTasks = validateAtomizedTasks;
function isInDTE() {
    if (process.env['NX_CLOUD_DISTRIBUTED_EXECUTION_ID'] ||
        process.env['NX_AGENT_NAME']) {
        return true;
    }
    // checks for DTE marker file - needed so we can check for DTE on the main nx job
    const nxCacheDirectory = process.env.NX_CACHE_DIRECTORY
        ? [process.env['NX_CACHE_DIRECTORY']]
        : ['node_modules', '.cache', 'nx'];
    const dir = (0, path_1.join)(workspace_root_1.workspaceRoot, ...nxCacheDirectory);
    const dteMarker = (0, path_1.join)(dir, 'NX_CLOUD_DISTRIBUTED_EXECUTION');
    if ((0, fs_1.existsSync)(dteMarker) && (0, fs_extra_1.readFileSync)(dteMarker, 'utf-8') === 'true') {
        return true;
    }
    return false;
}
