1use std::sync::Arc;
2
3use askama::Template;
4use axum::{extract::Query, response::IntoResponse, Extension};
5use serde::Deserialize;
6
7use crate::{
8 git::Commit,
9 into_response,
10 methods::{
11 filters,
12 repo::{Repository, RepositoryPath, Result},
13 },
14 Git,
15};
16
17#[derive(Template)]
18#[template(path = "repo/commit.html")]
19pub struct View {
20 pub repo: Repository,
21 pub commit: Arc<Commit>,
22 pub branch: Option<Arc<str>>,
23 pub dl_branch: Arc<str>,
24 pub id: Option<String>,
25}
26
27#[derive(Deserialize)]
28pub struct UriQuery {
29 pub id: Option<String>,
30 #[serde(rename = "h")]
31 pub branch: Option<Arc<str>>,
32}
33
34pub async fn handle(
35 Extension(repo): Extension<Repository>,
36 Extension(RepositoryPath(repository_path)): Extension<RepositoryPath>,
37 Extension(git): Extension<Arc<Git>>,
38 Query(query): Query<UriQuery>,
39) -> Result<impl IntoResponse> {
40 let open_repo = git.repo(repository_path, query.branch.clone()).await?;
41
42 let dl_branch = if let Some(branch) = query.branch.clone() {
43 branch
44 } else {
45 Arc::from(
46 open_repo
47 .clone()
48 .default_branch()
49 .await
50 .ok()
51 .flatten()
52 .unwrap_or_else(|| "master".to_string()),
53 )
54 };
55
56 let commit = if let Some(commit) = query.id.as_deref() {
57 open_repo.commit(commit).await?
58 } else {
59 Arc::new(open_repo.latest_commit().await?)
60 };
61
62 Ok(into_response(View {
63 repo,
64 commit,
65 branch: query.branch,
66 id: query.id,
67 dl_branch,
68 }))
69}