import { repoDb } from "./scoped-db";
import { withStore } from "./git/store";
import { compareCommits } from "./git/history";
import { diffTreesCached } from "./git/diff";
import { isReachableFrom } from "./git/reachable";
import { badRequest, notFoundError } from "./errors";
import type { PullRow } from "./pulls";
import type { DiffResult, RepoRow } from "~/lib/types";
import type { GitStore } from "./git/store";
const MAX_PICKER_COMMITS = 100;
/**
* A "changes since" commit must belong to this pull request: a commit of the pull request, its merge
* base, a head the pull request had before (reviews and head_pushed events record them), or an ancestor
* of the current head or base. Anything else in the head store, e.g. a private fork's other branches, is
* refused (AZ-A3).
*/
async function sinceBelongsToPull(pull: PullRow, headStore: GitStore, since: string, mergeBase: string | null) {
if (since === mergeBase || since === pull.merge_base_sha || since === pull.base_sha) return true;
const recorded = await repoDb(pull.repo_id).first(
`SELECT 1 AS ok FROM reviews WHERE issue_id = ?1 AND commit_sha = ?2
UNION SELECT 1 FROM issue_events WHERE issue_id = ?1 AND kind = 'head_pushed'
AND (json_extract(data, '$.before') = ?2 OR json_extract(data, '$.after') = ?2)
LIMIT 1`,
pull.issue_id,
since,
);
if (recorded) return true;
return isReachableFrom(headStore, [pull.head_sha, pull.base_sha], since);
}
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 };
};