export interface PullRef { number: number title: string merged: boolean mergeCommitSha: string | null } export type ListPullsPage = (page: number) => Promise export type ListPullCommits = (index: number) => Promise /** * 把未发布提交的 sha 对上已合并 PR。 * 只认 Gitea 的 PR 提交列表 / squash 的 mergeCommitSha,不扫 commit message。 */ export async function indexCommitsByPull( shas: readonly string[], listPulls: ListPullsPage, listCommits: ListPullCommits, ): Promise> { const needed = new Set(shas) const out = new Map() if (needed.size === 0) return out for (let page = 1; page <= 20; page++) { const batch = await listPulls(page) if (batch.length === 0) break for (const pr of batch) { if (!pr.merged) continue const ref = { number: pr.number, title: pr.title } if (pr.mergeCommitSha && needed.has(pr.mergeCommitSha)) out.set(pr.mergeCommitSha, ref) const commits = await listCommits(pr.number) for (const sha of commits) { if (needed.has(sha)) out.set(sha, ref) } if (out.size === needed.size) return out } if (batch.length < 50) break } return out } export function attachPulls( commits: T[], index: Map, ): Array { return commits.map((c) => { const hit = index.get(c.sha) return hit ? { ...c, pr: hit.number, prTitle: hit.title } : c }) }