import { listCommits, toMirrorCommitSummary } from "./gitmirror"; import { loadPullDiff, loadPullInterdiff, type PullDiff } from "./pullDiff"; import { resolveChange, type PullDiffView, type PullInterdiffView, type Revspec } from "./pullRoute"; import type { Did } from "@atcute/lexicons/syntax"; import type { BobbinContext } from "./client"; import type { GitTarget } from "./gitclient"; import type { CommitSummary } from "./repo"; import type { DiffStyle } from "$lib/components/repo/pierre"; const COMMIT_LIMIT = 100; export interface PullPageDeps { ctx: BobbinContext; git: GitTarget; // todo: fork-based pulls read their head side from the source repo repo: Did; diffStyle: DiffStyle; } // what either mode hands the page export interface PullPageDiff { commits: CommitSummary[]; commitsError?: string; diff?: PullDiff; diffError?: string; } const listLog = async (deps: PullPageDeps, range: Revspec): Promise => { const page = await listCommits(deps.ctx, { repo: deps.repo, ranges: [`${range.base}..${range.head}`], limit: COMMIT_LIMIT }); return page.commits.map(toMirrorCommitSummary); }; const message = (cause: unknown) => (cause instanceof Error ? cause.message : String(cause)); const diffOf = (deps: PullPageDeps, spec: Revspec) => loadPullDiff( deps.ctx, deps.git, { baseRepo: deps.repo, baseCommit: spec.base, headRepo: deps.repo, headCommit: spec.head }, deps.diffStyle ); // both dids feed one scratch repo, so the pair is the same as a diff's const interdiffOf = (deps: PullPageDeps, a: Revspec, b: Revspec) => loadPullInterdiff( deps.ctx, deps.git, { baseRepo: deps.repo, baseCommit1: a.base, baseCommit2: a.head, headRepo: deps.repo, headCommit1: b.base, headCommit2: b.head }, deps.diffStyle ); // `version` is the whole round being viewed: the commit list always covers it, // whatever range the diff itself was narrowed to export const prepareDiff = async ( deps: PullPageDeps, view: PullDiffView, version: Revspec ): Promise => { const result: PullPageDiff = { commits: [] }; // the two failures are independent — a dead log still leaves a readable diff await Promise.all([ listLog(deps, version).then( (commits) => (result.commits = commits), (cause) => (result.commitsError = message(cause)) ), diffOf(deps, view).then( (diff) => (result.diff = diff), (cause) => (result.diffError = message(cause)) ) ]); return result; }; export const prepareInterdiff = async ( deps: PullPageDeps, view: PullInterdiffView ): Promise => { const result: PullPageDiff = { commits: [] }; let priorCommits: CommitSummary[] = []; try { [result.commits, priorCommits] = await Promise.all([ listLog(deps, view.to), view.changeId ? listLog(deps, view.from) : [] ]); } catch (cause) { result.commitsError = message(cause); } try { if (!view.changeId) { result.diff = await interdiffOf(deps, view.from, view.to); } else if (result.commitsError) { result.diffError = result.commitsError; } else { const target = resolveChange(view.changeId, priorCommits, result.commits, { from: view.from.base, to: view.to.base }); if (target.kind === "missing") { result.diffError = "Can't find commit with given change-id."; } else if (target.kind === "diff") { result.diff = await diffOf(deps, target.spec); } else { result.diff = await interdiffOf(deps, target.from, target.to); } } } catch (cause) { result.diffError = message(cause); } return result; };