"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MergeCommitFinalizationError = void 0;
exports.commitAndPushWorkerChanges = commitAndPushWorkerChanges;
const push_rejection_1 = require("../../../git/push-rejection");
const catalog_1 = require("../../../i18n/catalog");
const base_title_1 = require("../../../issues/base-title");
const constants_1 = require("../../../worker/constants");
const results_1 = require("../results");
async function commitAndPushWorkerChanges(input) {
    const message = input.commitMessage ??
        (0, results_1.buildCommitMessage)(input.issueDisplayId, (0, base_title_1.resolveIssueBaseTitle)(input.issue));
    if (input.mergeContext !== null &&
        input.workerOutcome === constants_1.WORKER_OUTCOMES.proceed) {
        await commitMergeWorkflowChanges({
            gitRepository: input.gitRepository,
            workspacePath: input.workspacePath,
            message,
            baseCommitOid: input.mergeContext.baseCommitOid,
            responseLanguage: input.responseLanguage,
        });
    }
    else if (input.mergeContext !== null) {
        return;
    }
    else if (await input.gitRepository.hasChanges(input.workspacePath)) {
        await input.gitRepository.commitAllChanges(input.workspacePath, message, [], {
            hookContext: "worker",
        });
    }
    if (await input.gitRepository.isBranchAheadOfBase(input.workspacePath, input.baseBranch)) {
        await pushBranchWithRemoteRebaseRetry({
            gitRepository: input.gitRepository,
            workspacePath: input.workspacePath,
            branchName: input.branchName,
            afterRebase: async () => {
                if (input.mergeContext !== null &&
                    input.workerOutcome === constants_1.WORKER_OUTCOMES.proceed) {
                    await commitMergeWorkflowChanges({
                        gitRepository: input.gitRepository,
                        workspacePath: input.workspacePath,
                        message,
                        baseCommitOid: input.mergeContext.baseCommitOid,
                        responseLanguage: input.responseLanguage,
                    });
                }
            },
        });
    }
}
async function pushBranchWithRemoteRebaseRetry(input) {
    try {
        await input.gitRepository.pushBranch(input.workspacePath, input.branchName, {
            hookContext: "worker",
        });
    }
    catch (error) {
        if (!(0, push_rejection_1.isPushRejectedError)(error)) {
            throw error;
        }
        await input.gitRepository.rebaseBranchOntoRemoteBranch({
            workspacePath: input.workspacePath,
            branchName: input.branchName,
        });
        await input.afterRebase();
        await input.gitRepository.pushBranch(input.workspacePath, input.branchName, {
            hookContext: "worker",
        });
    }
}
async function commitMergeWorkflowChanges(input) {
    const baseAlreadyIntegrated = await input.gitRepository.isCommitAncestorOfHead(input.workspacePath, input.baseCommitOid);
    if (baseAlreadyIntegrated) {
        if (await input.gitRepository.hasChanges(input.workspacePath)) {
            await input.gitRepository.commitAllChanges(input.workspacePath, input.message, [], { hookContext: "worker" });
        }
    }
    else {
        try {
            await input.gitRepository.commitAllChangesAsMerge({
                workspacePath: input.workspacePath,
                message: input.message,
                parentCommitOid: input.baseCommitOid,
                hookContext: "worker",
            });
        }
        catch (error) {
            throw new MergeCommitFinalizationError((0, catalog_1.translate)(input.responseLanguage, "run.mergeIntegration.finalizationFailed", {
                baseCommitOid: input.baseCommitOid,
            }), error);
        }
    }
    if (!(await input.gitRepository.isCommitAncestorOfHead(input.workspacePath, input.baseCommitOid))) {
        throw new MergeCommitFinalizationError((0, catalog_1.translate)(input.responseLanguage, "run.mergeIntegration.baseNotIntegrated", {
            baseCommitOid: input.baseCommitOid,
        }));
    }
}
class MergeCommitFinalizationError extends Error {
    cause;
    constructor(message, cause) {
        super(message);
        this.name = "MergeCommitFinalizationError";
        this.cause = cause;
    }
}
exports.MergeCommitFinalizationError = MergeCommitFinalizationError;
