use axum::Json; use axum::extract::{Path, Query, State}; use axum::http::HeaderValue; use axum::http::header; use axum::response::{IntoResponse, Response}; use jwt::extractor::AuthUser; use uuid::Uuid; use crate::error::RepoResult; use crate::features::RepoService; use crate::features::extras::{CommitsQuery, CommitsResponse}; use crate::features::git_ref::CommitView as CommitSummary; #[utoipa::path( get, path = "/repo/{channel_id}/{repo_id}/commits", tag = "repo", params(CommitsQuery), responses((status = 200, description = "List commits", body = CommitsResponse)), security(("bearer_auth" = [])) )] pub(crate) async fn list_handler( State(svc): State, AuthUser { claims }: AuthUser, Path((_, repo_id)): Path<(Uuid, Uuid)>, Query(q): Query, ) -> RepoResult> { let out = svc.list_commits(claims.sub, repo_id, q).await?; Ok(Json(out)) } #[utoipa::path( get, path = "/repo/{channel_id}/{repo_id}/git/commits/{sha}", tag = "repo", responses((status = 200, description = "Get a commit", body = CommitSummary)), security(("bearer_auth" = [])) )] pub(crate) async fn get_handler( State(svc): State, AuthUser { claims }: AuthUser, Path((_, repo_id, sha)): Path<(Uuid, Uuid, String)>, ) -> RepoResult> { let out = svc.get_commit(claims.sub, repo_id, &sha).await?; Ok(Json(out)) } #[utoipa::path( get, path = "/repo/{channel_id}/{repo_id}/git/commits/{sha}.{diff_type}", tag = "repo", responses((status = 200, description = "Get commit diff or patch", content_type = "text/plain")), security(("bearer_auth" = [])) )] pub(crate) async fn diff_handler( State(svc): State, AuthUser { claims }: AuthUser, Path((_, repo_id, sha_dot_type)): Path<(Uuid, Uuid, String)>, ) -> RepoResult { let (sha, diff_type) = sha_dot_type .rsplit_once('.') .ok_or_else(|| crate::error::RepoError::BadRequest("expected '.diff|patch'".into()))?; let body = svc .get_commit_diff_or_patch(claims.sub, repo_id, sha, diff_type) .await?; let resp = ( [( header::CONTENT_TYPE, HeaderValue::from_static("text/plain; charset=utf-8"), )], body.content, ) .into_response(); Ok(resp) }