208 lines · 8.1 KB
import { first, run } from "./db";
import { repoDb, stmt } from "./scoped-db";
import { registerLocator } from "./scoped-db/locators";
import { scopedId } from "./scoped-db/ids";
import { captureServerEvent } from "./analytics";
import { badRequest, conflict, forbidden, notFoundError } from "./errors";
import { emitNotification, emitWebhook, recordActivity } from "./events/emit";
import { compareCommits } from "./git/history";
import { canBridge, isPullHeadRepo } from "./git/bridge-policy";
import { branchSha, listRefs } from "./git/refs";
import { withStore } from "./git/store";
import { deleteRef } from "./git/writer";
import { allocateIssueNumber, indexIssue } from "./issues";
import { pullUrl } from "./pull-access";
import { assertNotArchived } from "./repos";
import { afterPullChange } from "./pull-events";
import { addIssueEvent, MergeError, mergeGate, performMerge } from "./pulls";
import type { PullRow } from "./pulls";
import { hasPermission, repoPermission } from "./repos";
import type { MergeMethod, Permission, RepoRow, Viewer } from "~/lib/types";

/**
 * The repo owned by `ownerName` that may be a pull request head for `repo`: itself or a live direct fork.
 * The parent is deliberately not a candidate: a fork owner only reads the parent, and a pull request
 * "from parent into fork" would relay the parent's future history into the fork (GIT-A1).
 */
export async function findForkHead(repo: RepoRow, ownerName: string): Promise<RepoRow | null> {
  return first<RepoRow>(
    `SELECT r.*, a.name AS owner_name, a.disabled_at AS owner_disabled_at, a.disabled_reason AS owner_disabled_reason FROM repos r JOIN accounts a ON a.id = r.owner_id
     WHERE a.name = ? AND ((r.fork_of_id = ? AND r.detached = 0) OR r.id = ?)`,
    ownerName,
    repo.id,
    repo.id,
  );
}

/**
 * Opens a pull request once the caller has resolved and authorized the head repository. The head must be
 * the base or a live fork of it, and the author needs write on the head: a pull request stands for
 * branches its author can push to, and `pullHeadAccessible` re-checks their read on both sides for as