import { z } from "zod";
import { batch, first, stmt } from "../db";
import { badRequest, conflict, notFoundError } from "../errors";
import { recordActivity } from "../events/emit";
import { branchSha, listRefs, resolveRevision } from "../git/refs";
import { ZERO_SHA } from "../git/store";
import { announcePush, assertDirectUpdate, rethrowPush } from "../git/web-commit";
import { createBranch as pushBranch, deleteRef, isValidRefName } from "../git/writer";
import { assertBelowCap, CAPS, limitWrite } from "../limits";
import { repoMoveStatements } from "../redirects";
import { disableRepoConfigOnTransfer, repoOwnershipChangeStatements } from "../integrations/ownership";
import { rebillRepoLfs } from "../lfs/objects";
import { assertCanTransfer } from "../fork-policy";
import { syncHostingForRepo } from "../sites/sync";
import { noContent, ownerAccount, readJson, repoJson, requireAccountScope, requireScopedRepo } from "./http";
import type { ApiContext } from "./http";
const MAX_LISTED_REFS = 90;
export async function listBranchesApi(ctx: ApiContext, owner: string, name: string): Promise<Response> {
const { repo } = await requireScopedRepo(ctx, owner, name, "contents", "read");
const refs = await listRefs(repo);
return Response.json({
default_branch: repo.default_branch,
branches: refs.branches.slice(0, MAX_LISTED_REFS).map((branch) => ({ name: branch.name, sha: branch.sha })),
});
}
const branchInput = z.object({
name: z.string().min(1),
from: z.string().min(1),
});
/** Same steps as the createBranch server fn, including protection and push-rule checks. */
export async function createBranchApi(ctx: ApiContext, owner: string, name: string): Promise<Response> {
const data = await readJson(ctx.request, branchInput);
await limitWrite(ctx.viewer);
const { repo, permission } = await requireScopedRepo(ctx, owner, name, "contents", "write");
if (!isValidRefName(data.name)) throw badRequest("Invalid branch name");
const refs = await listRefs(repo);