"use server"; import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; import { person } from "@/lib/actor"; import { filter, findFirst } from "@/lib/db"; import { getEvent } from "@/lib/events"; import { isRevertable } from "@/lib/event-text"; import { GitError } from "@/lib/git"; import { RevertError, revertCommit, revertPush } from "@/lib/revert"; import { findRepoById } from "@/lib/repos"; import { ActionError, repoForAction, viewerOrThrow } from "./guard"; /** Undoes a push one of the viewer's agents made, from the activity page. */ export async function revertPushAction(eventId: string) { const viewer = await viewerOrThrow(); // Only pushes your own agents made are yours to undo here. const own = await findFirst("events", filter("id = {:id} && actor = {:actor}", { id: eventId, actor: viewer.id }), { fields: "id" }); const event = own ? await getEvent(eventId) : null; if (!event || !isRevertable(event)) throw new ActionError("That push can't be undone."); const record = await findRepoById(event.repoId); if (!record) throw new ActionError("The repository was deleted."); const { repo } = await repoForAction(record.owner, record.name, "write"); let result: Awaited>; try { result = await revertPush(repo, person(viewer.id), event); } catch (e) { if (e instanceof RevertError || e instanceof GitError) throw new ActionError(e.message); throw e; } revalidatePath("/settings/activity"); redirect(result.pull ? `/${repo.owner}/${repo.name}/pulls/${result.pull}` : `/${repo.owner}/${repo.name}/commit/${result.commit}`); } /** Reverts one commit, from the commit page or a commit list: a new commit on the branch that has it (or a pull request, if that branch is protected). */ export async function revertCommitAction(owner: string, name: string, sha: string) { const { repo, viewer } = await repoForAction(owner, name, "write"); let result: Awaited>; try { result = await revertCommit(repo, person(viewer.id), sha); } catch (e) { if (e instanceof RevertError || e instanceof GitError) throw new ActionError(e.message); throw e; } revalidatePath(`/${repo.owner}/${repo.name}`, "layout"); redirect(result.pull ? `/${repo.owner}/${repo.name}/pulls/${result.pull}` : `/${repo.owner}/${repo.name}/commit/${result.commit}`); }