feat: 同步全部分支的 Git 提交,不再仅限默认分支
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 46m54s

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
zyc 2026-04-21 10:57:04 +08:00
parent 4fa69ca2bc
commit 7cd8bc1b9b
2 changed files with 46 additions and 28 deletions

View File

@ -58,12 +58,22 @@ export async function getRepos(): Promise<GiteaRepo[]> {
return Array.isArray(data) ? data : []; return Array.isArray(data) ? data : [];
} }
export async function getCommits(owner: string, repo: string, since?: string): Promise<GiteaCommit[]> { export interface GiteaBranch {
name: string;
}
export async function getBranches(owner: string, repo: string): Promise<GiteaBranch[]> {
const data = await giteaGet<GiteaBranch[]>(`/repos/${owner}/${repo}/branches?limit=50`);
return Array.isArray(data) ? data : [];
}
export async function getCommits(owner: string, repo: string, since?: string, branch?: string): Promise<GiteaCommit[]> {
// 分页拉取所有 commit每页 50最多 10 页 = 500 条) // 分页拉取所有 commit每页 50最多 10 页 = 500 条)
const all: GiteaCommit[] = []; const all: GiteaCommit[] = [];
for (let page = 1; page <= 10; page++) { for (let page = 1; page <= 10; page++) {
let path = `/repos/${owner}/${repo}/commits?limit=50&page=${page}`; let path = `/repos/${owner}/${repo}/commits?limit=50&page=${page}`;
if (since) path += `&since=${since}`; if (since) path += `&since=${since}`;
if (branch) path += `&sha=${encodeURIComponent(branch)}`;
const data = await giteaGet<GiteaCommit[]>(path); const data = await giteaGet<GiteaCommit[]>(path);
if (!Array.isArray(data) || data.length === 0) break; if (!Array.isArray(data) || data.length === 0) break;
all.push(...data); all.push(...data);

View File

@ -70,35 +70,43 @@ export async function syncGitea(): Promise<void> {
for (const repo of reposToSync) { for (const repo of reposToSync) {
try { try {
// Sync commits // Sync commits from all branches
const commits = await giteaClient.getCommits(repo.owner, repo.name); const branches = await giteaClient.getBranches(repo.owner, repo.name);
for (const commit of commits) { const seenShas = new Set<string>();
const existingCommit = await db.query.gitCommits.findFirst({
where: eq(gitCommits.sha, commit.sha),
});
if (!existingCommit) { for (const branch of branches) {
const userId = await resolveAuthor( const commits = await giteaClient.getCommits(repo.owner, repo.name, undefined, branch.name);
commit.commit.author.email, for (const commit of commits) {
null if (seenShas.has(commit.sha)) continue;
); seenShas.add(commit.sha);
const now = new Date(); const existingCommit = await db.query.gitCommits.findFirst({
await db.insert(gitCommits).values({ where: eq(gitCommits.sha, commit.sha),
id: uuid(),
repoName: repo.name,
sha: commit.sha,
authorEmail: commit.commit.author.email,
authorName: commit.commit.author.name,
userId,
message: commit.commit.message,
additions: commit.stats?.additions || 0,
deletions: commit.stats?.deletions || 0,
committedAt: new Date(commit.commit.author.date),
createdAt: now,
updatedAt: now,
}); });
recordsProcessed++;
if (!existingCommit) {
const userId = await resolveAuthor(
commit.commit.author.email,
null
);
const now = new Date();
await db.insert(gitCommits).values({
id: uuid(),
repoName: repo.name,
sha: commit.sha,
authorEmail: commit.commit.author.email,
authorName: commit.commit.author.name,
userId,
message: commit.commit.message,
additions: commit.stats?.additions || 0,
deletions: commit.stats?.deletions || 0,
committedAt: new Date(commit.commit.author.date),
createdAt: now,
updatedAt: now,
});
recordsProcessed++;
}
} }
} }
@ -143,7 +151,7 @@ export async function syncGitea(): Promise<void> {
recordsProcessed++; recordsProcessed++;
} }
console.info(`[SYNC] Repo ${repo.owner}/${repo.name}: synced`); console.info(`[SYNC] Repo ${repo.owner}/${repo.name}: synced (${branches.length} branches)`);
} catch (repoErr) { } catch (repoErr) {
const msg = repoErr instanceof Error ? repoErr.message : 'Unknown error'; const msg = repoErr instanceof Error ? repoErr.message : 'Unknown error';
console.error(`[SYNC] Repo ${repo.owner}/${repo.name} failed:`, msg); console.error(`[SYNC] Repo ${repo.owner}/${repo.name} failed:`, msg);