use crate::{ApiResponse, error::ApiError}; use actix_web::{HttpResponse, Result, web}; use service::AppService; use service::git::repo::{ ConfigBoolResponse, ConfigDeleteQuery, ConfigEntriesQuery, ConfigGetQuery, ConfigSetRequest, ConfigSnapshotResponse, DescriptionQuery, DescriptionResponse, GitUpdateRepoRequest, MergeAnalysisQuery, MergeAnalysisResponse, MergeCommitsRequest, MergeRefAnalysisQuery, MergeTreesRequest, MergeheadInfoResponse, }; use session::Session; #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/description", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Get repository description", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_description_get( service: web::Data, session: Session, path: web::Path<(String, String)>, ) -> Result { let (namespace, repo_name) = path.into_inner(); let resp = service .git_description_get(namespace, repo_name, &session) .await?; Ok(ApiResponse::ok(resp).to_response()) } #[utoipa::path( put, path = "/api/repos/{namespace}/{repo}/git/description", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), request_body = DescriptionQuery, responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Set repository description", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_description_set( service: web::Data, session: Session, path: web::Path<(String, String)>, body: web::Json, ) -> Result { let (namespace, repo_name) = path.into_inner(); let resp = service .git_description_set(namespace, repo_name, body.into_inner(), &session) .await?; Ok(ApiResponse::ok(resp).to_response()) } #[utoipa::path( delete, path = "/api/repos/{namespace}/{repo}/git/description", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Reset repository description", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_description_reset( service: web::Data, session: Session, path: web::Path<(String, String)>, ) -> Result { let (namespace, repo_name) = path.into_inner(); let resp = service .git_description_reset(namespace, repo_name, &session) .await?; Ok(ApiResponse::ok(resp).to_response()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/description/exists", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Check if repository description exists", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_description_exists( service: web::Data, session: Session, path: web::Path<(String, String)>, ) -> Result { let (namespace, repo_name) = path.into_inner(); let resp = service .git_description_exists(namespace, repo_name, &session) .await?; Ok(ApiResponse::ok(serde_json::json!({"exists": resp})).to_response()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/config/entries", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "List repository config entries", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_config_entries( service: web::Data, session: Session, path: web::Path<(String, String)>, query: web::Query, ) -> Result { let (namespace, repo_name) = path.into_inner(); let resp = service .git_config_entries(namespace, repo_name, query.into_inner(), &session) .await?; Ok(ApiResponse::ok(resp).to_response()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/config/{key}", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ("key" = String, Path, description = "Config key"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Get repository config value", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_config_get( service: web::Data, session: Session, path: web::Path<(String, String, String)>, query: web::Query, ) -> Result { let (namespace, repo_name, key) = path.into_inner(); let mut req = query.into_inner(); req.key = key; let resp = service .git_config_get(namespace, repo_name, req, &session) .await?; Ok(ApiResponse::ok(serde_json::json!({"value": resp})).to_response()) } #[utoipa::path( put, path = "/api/repos/{namespace}/{repo}/git/config/{key}", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ("key" = String, Path, description = "Config key"), ), request_body = ConfigSetRequest, responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Set repository config value"), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_config_set( service: web::Data, session: Session, path: web::Path<(String, String, String)>, body: web::Json, ) -> Result { let (namespace, repo_name, key) = path.into_inner(); let mut req = body.into_inner(); req.key = key; service .git_config_set(namespace, repo_name, req, &session) .await?; Ok(crate::api_success()) } #[utoipa::path( delete, path = "/api/repos/{namespace}/{repo}/git/config/{key}", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ("key" = String, Path, description = "Config key"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Delete repository config key"), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_config_delete( service: web::Data, session: Session, path: web::Path<(String, String, String)>, query: web::Query, ) -> Result { let (namespace, repo_name, key) = path.into_inner(); let mut req = query.into_inner(); req.key = key; service .git_config_delete(namespace, repo_name, req, &session) .await?; Ok(crate::api_success()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/config/{key}/has", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ("key" = String, Path, description = "Config key"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Check if repository config key exists", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_config_has( service: web::Data, session: Session, path: web::Path<(String, String, String)>, query: web::Query, ) -> Result { let (namespace, repo_name, key) = path.into_inner(); let mut req = query.into_inner(); req.key = key; let resp = service .git_config_has(namespace, repo_name, req, &session) .await?; Ok(ApiResponse::ok(resp).to_response()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/merge/analysis/{their_oid}", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ("their_oid" = String, Path, description = "The OID to analyze merge against"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Perform merge analysis", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_merge_analysis( service: web::Data, session: Session, path: web::Path<(String, String, String)>, query: web::Query, ) -> Result { let (namespace, repo_name, their_oid) = path.into_inner(); let mut req = query.into_inner(); req.their_oid = their_oid; let resp = service .git_merge_analysis(namespace, repo_name, req, &session) .await?; Ok(ApiResponse::ok(resp).to_response()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/merge/analysis/{ref_name}/{their_oid}", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ("ref_name" = String, Path, description = "Reference name"), ("their_oid" = String, Path, description = "The OID to analyze merge against"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Perform merge analysis for a specific ref", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_merge_analysis_for_ref( service: web::Data, session: Session, path: web::Path<(String, String, String, String)>, query: web::Query, ) -> Result { let (namespace, repo_name, ref_name, their_oid) = path.into_inner(); let mut req = query.into_inner(); req.ref_name = ref_name; req.their_oid = their_oid; let resp = service .git_merge_analysis_for_ref(namespace, repo_name, req, &session) .await?; Ok(ApiResponse::ok(resp).to_response()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/merge/base/{oid1}/{oid2}", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ("oid1" = String, Path, description = "First commit OID"), ("oid2" = String, Path, description = "Second commit OID"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Get merge base of two commits", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_merge_base( service: web::Data, session: Session, path: web::Path<(String, String, String, String)>, ) -> Result { let (namespace, repo_name, oid1, oid2) = path.into_inner(); let resp = service .git_merge_base(namespace, repo_name, oid1, oid2, &session) .await?; Ok(ApiResponse::ok(serde_json::json!({"merge_base": resp})).to_response()) } #[utoipa::path( post, path = "/api/repos/{namespace}/{repo}/git/merge/commits", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), request_body = MergeCommitsRequest, responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Merge commits"), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_merge_commits( service: web::Data, session: Session, path: web::Path<(String, String)>, body: web::Json, ) -> Result { let (namespace, repo_name) = path.into_inner(); service .git_merge_commits(namespace, repo_name, body.into_inner(), &session) .await?; Ok(crate::api_success()) } #[utoipa::path( post, path = "/api/repos/{namespace}/{repo}/git/merge/trees", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), request_body = MergeTreesRequest, responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Merge trees"), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_merge_trees( service: web::Data, session: Session, path: web::Path<(String, String)>, body: web::Json, ) -> Result { let (namespace, repo_name) = path.into_inner(); service .git_merge_trees(namespace, repo_name, body.into_inner(), &session) .await?; Ok(crate::api_success()) } #[utoipa::path( post, path = "/api/repos/{namespace}/{repo}/git/merge/abort", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Abort an in-progress merge"), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_merge_abort( service: web::Data, session: Session, path: web::Path<(String, String)>, ) -> Result { let (namespace, repo_name) = path.into_inner(); service .git_merge_abort(namespace, repo_name, &session) .await?; Ok(crate::api_success()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/merge/in-progress", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Check if merge is in progress", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_merge_is_in_progress( service: web::Data, session: Session, path: web::Path<(String, String)>, ) -> Result { let (namespace, repo_name) = path.into_inner(); let resp = service .git_merge_is_in_progress(namespace, repo_name, &session) .await?; Ok(ApiResponse::ok(serde_json::json!({"in_progress": resp})).to_response()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/merge/heads", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "List merge heads", body = ApiResponse>), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_mergehead_list( service: web::Data, session: Session, path: web::Path<(String, String)>, ) -> Result { let (namespace, repo_name) = path.into_inner(); let resp = service .git_mergehead_list(namespace, repo_name, &session) .await?; Ok(ApiResponse::ok(resp).to_response()) } #[utoipa::path( get, path = "/api/repos/{namespace}/{repo}/git/merge/is-conflicted", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Check if merge has conflicts", body = ApiResponse), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_merge_is_conflicted( service: web::Data, session: Session, path: web::Path<(String, String)>, ) -> Result { let (namespace, repo_name) = path.into_inner(); let resp = service .git_merge_is_conflicted(namespace, repo_name, &session) .await?; Ok(ApiResponse::ok(serde_json::json!({"is_conflicted": resp})).to_response()) } #[utoipa::path( patch, path = "/api/repos/{namespace}/{repo}/git", params( ("namespace" = String, Path, description = "Project namespace"), ("repo" = String, Path, description = "Repository name"), ), request_body = GitUpdateRepoRequest, responses( (status = 401, description = "Unauthorized", body = ApiResponse), (status = 200, description = "Update repository settings"), (status = 404, description = "Not found", body = ApiResponse), ), tag = "Git" )] pub async fn git_update_repo( service: web::Data, session: Session, path: web::Path<(String, String)>, body: web::Json, ) -> Result { let (namespace, repo_name) = path.into_inner(); service .git_update_repo(namespace, repo_name, body.into_inner(), &session) .await?; Ok(crate::api_success()) }