324 lines · 12.1 KB
import { first } from "./db";
import { repoDb } from "./scoped-db";
import { loadRepoById } from "./repos";
import { withStore } from "./git/store";
import { isAncestor } from "./git/history";
import { pushToArtifacts, PushRejectedError } from "./git/writer";
import { addIssueEvent, loadPullByIssueId, PULL_SELECT } from "./pulls";
import type { PullRow } from "./pulls";
import { planRebase, RebaseConflictError } from "./pull-rebase";
import type { MergeMethod } from "~/lib/types";

/**
 * Stacked pull requests. A pull request is stacked when its base branch is the head branch of another
 * open pull request in the same repository, so stacks need no extra bookkeeping and work with any
 * client (git, gt, jj, git-town) that sets the base. When a parent merges, its children are retargeted
 * onto the parent's base and, if the merge rewrote history (squash or rebase), restacked so they keep
 * showing only their own commits.
 */

const MAX_STACK_DEPTH = 25;
const MAX_STACK_SIZE = 50;
const MAX_CHILDREN = 20;
const SYSTEM_COMMITTER = { name: "gitfor", email: "stacks@noreply.gitfor" };

export type StackEntry = {
  issueId: string;
  number: number;
  title: string;
  state: "open" | "closed";
  merged: boolean;
  draft: boolean;
  headRef: string;
  baseRef: string;
  /** Distance from the bottom of the stack; siblings share a depth. */
  depth: number;
  current: boolean;
};

export type StackLoaders = {
  parent(pull: PullRow): Promise<PullRow | null>;