//! Git issue tracker routes: read-only list and detail views. //! Also includes the commit-message issue reference parser and process-push endpoint. mod issues; mod push_refs; mod settings; use axum::routing::get; use crate::{ AppState, config::Config, csrf::{CsrfRouter, post_csrf, post_csrf_skip}, routes::git::{repos_root, resolve_repo}, }; /// Register all git issue routes. pub fn git_issue_routes() -> CsrfRouter { CsrfRouter::new() // Issue list + detail (read-only) .route_get("/git/{owner}/{repo}/issues", get(issues::issue_list)) .route_get( "/git/{owner}/{repo}/issues/{number}", get(issues::issue_detail), ) // Repo settings .route_get( "/git/{owner}/{repo}/settings", get(settings::repo_settings_form), ) .route( "/git/{owner}/{repo}/settings", post_csrf(settings::repo_settings_save), ) .route( "/git/{owner}/{repo}/settings/delete", post_csrf(settings::repo_settings_delete), ) // Internal: commit-message issue references .route( "/api/internal/issues/process-push", post_csrf_skip( "internal git push hook, HMAC bearer", push_refs::process_push, ), ) } /// Get the default branch name for a repo (for nav bar links). async fn default_ref(config: &Config, owner: &str, repo_name: &str) -> String { let Ok(root) = repos_root(config) else { return "main".to_string(); }; let owner = owner.to_string(); let repo_name = repo_name.to_string(); // libgit2 open + repo_info are blocking filesystem work; run them on the // blocking pool so a nav-bar ref lookup can't stall a worker thread // (ultra-fuzz Run 10 Perf S4). tokio::task::spawn_blocking( move || match crate::git::open_repo(&root, &owner, &repo_name) { Ok(repo) => crate::git::repo_info(&repo, &repo_name).default_branch, Err(_) => "main".to_string(), }, ) .await .unwrap_or_else(|_| "main".to_string()) }