use std::sync::Arc; use askama::Template; use axum::{extract::Query, response::IntoResponse, Extension}; use serde::Deserialize; use crate::{ git::{Commit, OpenRepository}, into_response, methods::{ filters, repo::{Repository, RepositoryPath, Result}, }, Git, }; #[derive(Template)] #[template(path = "repo/commit.html")] pub struct View { pub repo: Repository, pub commit: Arc<Commit>, pub branch: Option<Arc<str>>, pub dl_branch: Arc<str>, pub id: Option<String>, } #[derive(Deserialize)] pub struct UriQuery { pub id: Option<String>, #[serde(rename = "h")] pub branch: Option<Arc<str>>, } pub async fn handle( Extension(repo): Extension<Repository>, Extension(RepositoryPath(repository_path)): Extension<RepositoryPath>, Extension(git): Extension<Arc<Git>>, Query(query): Query<UriQuery>, ) -> Result<impl IntoResponse> { let open_repo = git.repo(repository_path, query.branch.clone()).await?; let (dl_branch, commit) = tokio::try_join!( fetch_dl_branch(query.branch.clone(), open_repo.clone()), fetch_commit(query.id.as_deref(), open_repo), )?; Ok(into_response(View { repo, commit, branch: query.branch, id: query.id, dl_branch, })) } async fn fetch_commit( commit_id: Option<&str>, open_repo: Arc<OpenRepository>, ) -> Result<Arc<Commit>> { Ok(if let Some(commit) = commit_id { open_repo.commit(commit, true).await? } else { Arc::new(open_repo.latest_commit(true).await?) }) } async fn fetch_dl_branch( branch: Option<Arc<str>>, open_repo: Arc<OpenRepository>, ) -> Result<Arc<str>> { if let Some(branch) = branch.clone() { Ok(branch) } else { Ok(Arc::from( open_repo .clone() .default_branch() .await? .unwrap_or_else(|| "master".to_string()), )) } }