gitdataai/lib/service/git/contributor.rs
2026-05-30 01:38:40 +08:00

57 lines
1.7 KiB
Rust

use db::sqlx;
use serde::{Deserialize, Serialize};
use session::Session;
use utoipa::ToSchema;
use crate::{AppService, Pagination, error::AppError};
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ContributorDto {
pub name: String,
pub email: String,
#[schema(value_type = Option<String>)]
pub user_id: Option<uuid::Uuid>,
pub commit_count: i64,
}
impl AppService {
pub async fn git_repo_contributors(
&self,
ctx: &Session,
wk_name: &str,
repo_name: &str,
pagination: Pagination,
) -> Result<Vec<ContributorDto>, AppError> {
let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
let offset = pagination.offset() as i64;
let limit = pagination.limit() as i64;
let rows = sqlx::query_as::<_, (String, String, Option<uuid::Uuid>, Option<i64>)>(
"SELECT rc.name, rc.email, rc.user, COUNT(rco.id)::bigint AS commit_count \
FROM repo_committer rc \
LEFT JOIN repo_commit rco ON rc.id = rco.author \
WHERE rc.repo = $1 \
GROUP BY rc.id, rc.name, rc.email, rc.user \
ORDER BY commit_count DESC \
OFFSET $2 LIMIT $3",
)
.bind(repo.id)
.bind(offset)
.bind(limit)
.fetch_all(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
Ok(rows
.into_iter()
.map(|(name, email, user_id, commit_count)| ContributorDto {
name,
email,
user_id,
commit_count: commit_count.unwrap_or(0),
})
.collect())
}
}