117 lines · 5.2 KB
import { createServerFn } from "@tanstack/react-start";
import { withAuthorAccounts } from "~/server/commit-authors";
import { limitHeavy, limitWrite } from "~/server/limits";
import { z } from "zod";
import { requireViewer, viewerMiddleware } from "./middleware";
import { repoDb } from "~/server/scoped-db";
import { requireRepoAccess } from "~/server/repos";
import { branchSha, listRefs, resolveRevision } from "~/server/git/refs";
import { createBranch as pushBranch, deleteRef, isValidRefName } from "~/server/git/writer";
import { compareBranches } from "~/server/git/compare";
import { aiAccessFor } from "~/server/pull-describe/service";
import { badRequest, conflict, notFoundError } from "~/server/errors";
import { ZERO_SHA } from "~/server/git/store";
import { repoRef } from "~/lib/validation";
import { announcePush as announce, assertDirectUpdate, commitFileChange, rethrowPush } from "~/server/git/web-commit";

const MAX_EDIT_BYTES = 5 * 1024 * 1024;
const encoder = new TextEncoder();

export const createBranch = createServerFn({ method: "POST" })
  .middleware([viewerMiddleware])
  .validator(repoRef.extend({ name: z.string().min(1), from: z.string().min(1) }))
  .handler(async ({ data, context }) => {
    const viewer = requireViewer(context.viewer);
    await limitWrite(viewer);
    const { repo, permission } = await requireRepoAccess(data.owner, data.repo, viewer, "write");
    if (!isValidRefName(data.name)) throw badRequest("Invalid branch name");
    const refs = await listRefs(repo);
    if (branchSha(refs, data.name)) throw conflict("Branch already exists");
    const source = resolveRevision(refs, data.from);
    if (!source) throw notFoundError("Source ref not found");
    await assertDirectUpdate(repo, permission, data.name, false);
    await pushBranch(repo, data.name, source.sha).catch(rethrowPush);
    await announce(repo, viewer, `refs/heads/${data.name}`, ZERO_SHA, source.sha);
    return { ok: true };
  });

export const deleteBranch = createServerFn({ method: "POST" })
  .middleware([viewerMiddleware])
  .validator(repoRef.extend({ name: z.string().min(1) }))