import "server-only";
import { commitExists, isAncestor, listBranches, revParse, type Branch } from "./git";
import { listPulls } from "./pulls";
import { listForks, type RepoRecord } from "./repos";
/** Branches pushed to this recently, without a pull request, get a suggestion to open one. */
const RECENT_MS = 2 * 86400e3;
export type RecentPush = { branch: Branch; fork: RepoRecord | null; compareHref: string };
/**
* Branches the viewer pushed to lately that could become pull requests into the repository's
* default branch: its own (for people with push access) and those of the viewer's forks of it.
* Branches whose commits the default branch already has are left out.
*/
export async function recentPushes(repo: RepoRecord & { defaultBranch: string | null }, viewerId: string | null, canWrite: boolean, limit = 3) {
if (!viewerId || !repo.defaultBranch) return [];
const base = `/${repo.owner}/${repo.name}`;
const baseSha = await revParse(repo.dir, `refs/heads/${repo.defaultBranch}`);
if (!baseSha) return [];
const open = (await listPulls(repo.id, { state: "open", perPage: 200 })).pulls;
const since = Date.now() - RECENT_MS;
const out: RecentPush[] = [];
const sources = [...(canWrite ? [null] : []), ...(await listForks(repo.id, viewerId)).filter((f) => f.ownerId === viewerId)];
for (const fork of sources) {
const dir = fork?.dir ?? repo.dir;
const taken = new Set(open.filter((p) => (fork ? p.headRepo?.id === fork.id : !p.headRepo)).map((p) => p.head));
for (const b of await listBranches(dir)) {
if (out.length >= limit) return out;
if (b.date <= since || taken.has(b.name) || (!fork && b.name === repo.defaultBranch)) continue;
// Already in the default branch: nothing to propose.
if ((await commitExists(repo.dir, b.sha)) && (await isAncestor(repo.dir, b.sha, baseSha))) continue;
const query = new URLSearchParams({ ...(fork ? { head_repo: `${fork.owner}/${fork.name}` } : {}), head: b.name });
out.push({ branch: b, fork, compareHref: `${base}/compare?${query}` });
}
}
return out;
}