import { run } from "./db";
import { withStore } from "./git/store";
import { compareCommits } from "./git/history";
import { diffTreesCached } from "./git/diff";
import { badRequest, notFoundError } from "./errors";
import type { PullRow } from "./pulls";
import type { DiffResult, RepoRow } from "~/lib/types";
const MAX_PICKER_COMMITS = 100;
export type DiffRange = { commit?: string; since?: string };
export type PullDiff = {
diff: DiffResult;
commits: Array<{ sha: string; shortSha: string; subject: string }>;
range: { kind: "all" } | { kind: "commit"; sha: string } | { kind: "since"; sha: string };
};
/**
* Diff for the Files tab: the whole pull request (merge base to head), a single commit, or the
* changes since a reviewed commit ("changes since last review").
*/
export async function pullDiff(pull: PullRow, repo: RepoRow, headRepo: RepoRow, range: DiffRange): Promise<PullDiff> {
return withStore(repo.artifacts_name, (baseStore) =>
withStore(headRepo.artifacts_name, async (headStore) => {
const comparison = await compareCommits(
baseStore,
pull.merged_at && pull.merge_base_sha ? pull.merge_base_sha : pull.base_sha,
headStore,
pull.head_sha,
);
const commits = comparison.commits
.slice(0, MAX_PICKER_COMMITS)
.map((commit) => ({ sha: commit.sha, shortSha: commit.shortSha, subject: commit.subject }));
const head = await headStore.commit(pull.head_sha);
if (!head) throw notFoundError("Head commit missing");
if (range.commit) {
const commit = comparison.commits.find((candidate) => candidate.sha === range.commit);
if (!commit) throw badRequest("That commit is not part of this pull request");