"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.recordInitialMigrationMetadata = recordInitialMigrationMetadata;
exports.finishMigrationProcess = finishMigrationProcess;
exports.runSingleMigration = runSingleMigration;
exports.getImplementationPath = getImplementationPath;
exports.modifyMigrationsJsonMetadata = modifyMigrationsJsonMetadata;
exports.addSuccessfulMigration = addSuccessfulMigration;
exports.addFailedMigration = addFailedMigration;
exports.addSkippedMigration = addSkippedMigration;
exports.readMigrationsJsonMetadata = readMigrationsJsonMetadata;
const child_process_1 = require("child_process");
const fs_1 = require("fs");
const path_1 = require("path");
const migrate_1 = require("./migrate");
function recordInitialMigrationMetadata(workspacePath, versionToMigrateTo) {
    const migrationsJsonPath = (0, path_1.join)(workspacePath, 'migrations.json');
    const parsedMigrationsJson = JSON.parse((0, fs_1.readFileSync)(migrationsJsonPath, 'utf-8'));
    const gitRef = (0, child_process_1.execSync)('git rev-parse HEAD', {
        cwd: workspacePath,
        encoding: 'utf-8',
    }).trim();
    const gitSubject = (0, child_process_1.execSync)('git log -1 --pretty=%s', {
        cwd: workspacePath,
        encoding: 'utf-8',
    }).trim();
    parsedMigrationsJson['nx-console'] = {
        initialGitRef: {
            ref: gitRef,
            subject: gitSubject,
        },
        targetVersion: versionToMigrateTo,
    };
    (0, fs_1.writeFileSync)(migrationsJsonPath, JSON.stringify(parsedMigrationsJson, null, 2));
}
function finishMigrationProcess(workspacePath, squashCommits, commitMessage) {
    const migrationsJsonPath = (0, path_1.join)(workspacePath, 'migrations.json');
    const parsedMigrationsJson = JSON.parse((0, fs_1.readFileSync)(migrationsJsonPath, 'utf-8'));
    const initialGitRef = parsedMigrationsJson['nx-console'].initialGitRef;
    if ((0, fs_1.existsSync)(migrationsJsonPath)) {
        (0, fs_1.rmSync)(migrationsJsonPath);
    }
    (0, child_process_1.execSync)('git add .', {
        cwd: workspacePath,
        encoding: 'utf-8',
    });
    (0, child_process_1.execSync)(`git commit -m "${commitMessage}" --no-verify`, {
        cwd: workspacePath,
        encoding: 'utf-8',
    });
    if (squashCommits && initialGitRef) {
        (0, child_process_1.execSync)(`git reset --soft ${initialGitRef.ref}`, {
            cwd: workspacePath,
            encoding: 'utf-8',
        });
        (0, child_process_1.execSync)(`git commit -m "${commitMessage}" --no-verify`, {
            cwd: workspacePath,
            encoding: 'utf-8',
        });
    }
}
async function runSingleMigration(workspacePath, migration, configuration) {
    try {
        modifyMigrationsJsonMetadata(workspacePath, addRunningMigration(migration.id));
        const gitRefBefore = (0, child_process_1.execSync)('git rev-parse HEAD', {
            cwd: workspacePath,
            encoding: 'utf-8',
        }).trim();
        // For Migrate UI, this current module is loaded either from:
        // 1. The CLI path to the migrated modules. The version of Nx is of the user's choosing. This may or may not have the new migrate API, so Console will check that `runSingleMigration` exists before using it.
        // 2. Bundled into Console, so the version is fixed to what we build Console with.
        const updatedMigrateModule = await Promise.resolve().then(() => require('./migrate.js'));
        const fileChanges = await updatedMigrateModule.runNxOrAngularMigration(workspacePath, migration, false, configuration.createCommits, configuration.commitPrefix || 'chore: [nx migration] ', undefined, true);
        const gitRefAfter = (0, child_process_1.execSync)('git rev-parse HEAD', {
            cwd: workspacePath,
            encoding: 'utf-8',
        }).trim();
        modifyMigrationsJsonMetadata(workspacePath, addSuccessfulMigration(migration.id, fileChanges.map((change) => ({
            path: change.path,
            type: change.type,
        })), gitRefAfter));
        if (gitRefBefore !== gitRefAfter) {
            (0, child_process_1.execSync)('git add migrations.json', {
                cwd: workspacePath,
                encoding: 'utf-8',
            });
            (0, child_process_1.execSync)('git commit --amend --no-verify --no-edit', {
                cwd: workspacePath,
                encoding: 'utf-8',
            });
        }
    }
    catch (e) {
        modifyMigrationsJsonMetadata(workspacePath, addFailedMigration(migration.id, e.message));
    }
    finally {
        modifyMigrationsJsonMetadata(workspacePath, removeRunningMigration(migration.id));
        (0, child_process_1.execSync)('git add migrations.json', {
            cwd: workspacePath,
            encoding: 'utf-8',
        });
    }
}
async function getImplementationPath(workspacePath, migration) {
    const { collection, collectionPath } = (0, migrate_1.readMigrationCollection)(migration.package, workspacePath);
    const { path } = (0, migrate_1.getImplementationPath)(collection, collectionPath, migration.name);
    return path;
}
function modifyMigrationsJsonMetadata(workspacePath, modify) {
    const migrationsJsonPath = (0, path_1.join)(workspacePath, 'migrations.json');
    const migrationsJson = JSON.parse((0, fs_1.readFileSync)(migrationsJsonPath, 'utf-8'));
    migrationsJson['nx-console'] = modify(migrationsJson['nx-console']);
    (0, fs_1.writeFileSync)(migrationsJsonPath, JSON.stringify(migrationsJson, null, 2));
}
function addSuccessfulMigration(id, fileChanges, ref) {
    return (migrationsJsonMetadata) => {
        const copied = { ...migrationsJsonMetadata };
        if (!copied.completedMigrations) {
            copied.completedMigrations = {};
        }
        copied.completedMigrations = {
            ...copied.completedMigrations,
            [id]: {
                type: 'successful',
                name: id,
                changedFiles: fileChanges,
                ref,
            },
        };
        return copied;
    };
}
function addFailedMigration(id, error) {
    return (migrationsJsonMetadata) => {
        const copied = { ...migrationsJsonMetadata };
        if (!copied.completedMigrations) {
            copied.completedMigrations = {};
        }
        copied.completedMigrations = {
            ...copied.completedMigrations,
            [id]: {
                type: 'failed',
                name: id,
                error,
            },
        };
        return copied;
    };
}
function addSkippedMigration(id) {
    return (migrationsJsonMetadata) => {
        const copied = { ...migrationsJsonMetadata };
        if (!copied.completedMigrations) {
            copied.completedMigrations = {};
        }
        copied.completedMigrations = {
            ...copied.completedMigrations,
            [id]: {
                type: 'skipped',
            },
        };
        return copied;
    };
}
function addRunningMigration(id) {
    return (migrationsJsonMetadata) => {
        migrationsJsonMetadata.runningMigrations = [
            ...(migrationsJsonMetadata.runningMigrations ?? []),
            id,
        ];
        return migrationsJsonMetadata;
    };
}
function removeRunningMigration(id) {
    return (migrationsJsonMetadata) => {
        migrationsJsonMetadata.runningMigrations =
            migrationsJsonMetadata.runningMigrations?.filter((n) => n !== id);
        if (migrationsJsonMetadata.runningMigrations?.length === 0) {
            delete migrationsJsonMetadata.runningMigrations;
        }
        return migrationsJsonMetadata;
    };
}
function readMigrationsJsonMetadata(workspacePath) {
    const migrationsJsonPath = (0, path_1.join)(workspacePath, 'migrations.json');
    const migrationsJson = JSON.parse((0, fs_1.readFileSync)(migrationsJsonPath, 'utf-8'));
    return migrationsJson['nx-console'];
}
