use actix_web::{HttpResponse, web}; use git::rpc::proto as p; use serde::{Deserialize, Serialize}; use service::AppService; use session::Session; use crate::error::ApiError; use crate::git::dto; fn ok_json(data: T) -> Result { Ok(HttpResponse::Ok().json(data)) } #[derive(Deserialize, utoipa::IntoParams)] pub struct WkRepoPath { pub wk: String, pub repo: String, } #[derive(Deserialize, utoipa::IntoParams)] pub struct WkRepoCommitPath { pub wk: String, pub repo: String, pub oid: String, } #[derive(Deserialize, utoipa::IntoParams)] pub struct HistoryQuery { pub limit: Option, pub skip: Option, pub sort: Option, pub branch: Option, } #[derive(Deserialize, utoipa::IntoParams)] pub struct CommitListQuery { #[serde(default)] pub summary: bool, #[serde(default)] pub refs: bool, pub prefix: Option, } #[utoipa::path( get, path = "/api/v1/workspace/{wk}/repos/{repo}/git/commits", params(WkRepoPath, CommitListQuery), responses( (status = 200, description = "Commit list / summary / refs / prefix", body = dto::CommitHistoryResponseDto), ), security(("session" = [])) )] pub async fn list_commits( session: Session, service: web::Data, path: web::Path, query: web::Query, ) -> Result { let WkRepoPath { wk, repo } = path.into_inner(); if let Some(prefix) = &query.prefix { let data: dto::CommitPrefixResponseDto = service .git_commit_prefix(&session, &wk, &repo, prefix.clone()) .await? .into(); return ok_json(data); } if query.refs { let data: dto::CommitRefsResponseDto = service.git_commit_refs(&session, &wk, &repo).await?.into(); return ok_json(data); } if query.summary { let data: dto::CommitSummaryResponseDto = service .git_commit_summary(&session, &wk, &repo) .await? .into(); return ok_json(data); } let data: dto::CommitHistoryResponseDto = service .git_commit_history(&session, &wk, &repo, 20, 0, 0, None) .await? .into(); ok_json(data) } #[utoipa::path( get, path = "/api/v1/workspace/{wk}/repos/{repo}/git/commits/history", params(WkRepoPath, HistoryQuery), responses((status = 200, description = "Commit history", body = dto::CommitHistoryResponseDto)), security(("session" = [])) )] pub async fn commit_history( session: Session, service: web::Data, path: web::Path, query: web::Query, ) -> Result { let WkRepoPath { wk, repo } = path.into_inner(); let data: dto::CommitHistoryResponseDto = service .git_commit_history( &session, &wk, &repo, query.limit.unwrap_or(20), query.skip.unwrap_or(0), query.sort.unwrap_or(0), query.branch.clone(), ) .await? .into(); ok_json(data) } #[utoipa::path( get, path = "/api/v1/workspace/{wk}/repos/{repo}/git/commits/{oid}", params(WkRepoCommitPath), responses((status = 200, description = "Commit info", body = dto::CommitInfoResponseDto)), security(("session" = [])) )] pub async fn commit_info( session: Session, service: web::Data, path: web::Path, ) -> Result { let WkRepoCommitPath { wk, repo, oid } = path.into_inner(); let data: dto::CommitInfoResponseDto = service .git_commit_info(&session, &wk, &repo, oid) .await? .into(); ok_json(data) } #[utoipa::path( post, path = "/api/v1/workspace/{wk}/repos/{repo}/git/commits/walk", params(WkRepoPath), request_body = Object, description = "CommitWalkParams", responses((status = 200, description = "Walk result", body = dto::CommitHistoryResponseDto)), security(("session" = [])) )] pub async fn commit_walk( session: Session, service: web::Data, path: web::Path, params: web::Json, ) -> Result { let WkRepoPath { wk, repo } = path.into_inner(); let proto_resp = service .git_commit_walk(&session, &wk, &repo, params.into_inner()) .await?; ok_json(dto::CommitHistoryResponseDto { commits: proto_resp.commits.into_iter().map(Into::into).collect(), }) } #[utoipa::path( post, path = "/api/v1/workspace/{wk}/repos/{repo}/git/commits/cherry-pick", params(WkRepoPath), request_body = Object, description = "CommitCherryPickParams", responses((status = 200, description = "Cherry-pick result", body = dto::CherryPickResponseDto)), security(("session" = [])) )] pub async fn cherry_pick( session: Session, service: web::Data, path: web::Path, params: web::Json, ) -> Result { let WkRepoPath { wk, repo } = path.into_inner(); let data: dto::CherryPickResponseDto = service .git_cherry_pick(&session, &wk, &repo, params.into_inner()) .await? .into(); ok_json(data) }