import { first } from "../db";
import { notFoundError } from "../errors";
import { hasPermission, loadRepo, repoPermission } from "../repos";
import { scopedRepoPermission } from "../token-scope";
import type { RequestCredential } from "../token-scope";
import { diffTreesCached } from "./diff";
import { compareCommits } from "./history";
import { assertVisibleRevision } from "./reachable";
import { listRefs, resolveRevision } from "./refs";
import type { ResolvedRevision } from "./refs";
import { withStore } from "./store";
import type { Comparison } from "./history";
import type { DiffResult, RepoRow, Viewer } from "~/lib/types";
export type BranchComparison = {
base: ResolvedRevision;
head: ResolvedRevision;
headRepo: RepoRow;
comparison: Comparison;
diff: DiffResult;
baseBranches: string[];
headBranches: string[];
};
/** Who is comparing: a signed-in viewer (full access) or a request credential whose token scope also applies. */
export type CompareAccess = Viewer | null | RequestCredential;
function isCredential(access: CompareAccess): access is RequestCredential {
return access !== null && "grant" in access;
}
async function canReadHead(repo: RepoRow, access: CompareAccess): Promise<boolean> {
if (isCredential(access)) return hasPermission(await scopedRepoPermission(repo, access, "contents"), "read");
return (await repoPermission(repo, access)) !== "none";
}
/**
* Resolves an `owner:branch` head to a fork the caller can read; bare names stay in the base repository. Every
* refusal is the same not-found, so the response never tells whether an unreadable private fork exists.
*/