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()),
))
}
}