raw
1use axum::{
2 extract::{Path, State},
3 http::StatusCode,
4 response::{IntoResponse as _, Response},
5};
6
7use crate::{
8 BileState,
9 error::Context as _,
10 git::Repository,
11 http::{
12 extractor::{Ref, RepoName},
13 response::{ErrorPage, Result, Xml},
14 },
15 utils::filters,
16};
17
18#[derive(askama::Template)]
19#[template(path = "log.xml")]
20struct RepoLogFeedTemplate<'a> {
21 repo: &'a Repository,
22 commits: Vec<git2::Commit<'a>>,
23 branch: String,
24 base_url: &'a str,
25}
26
27#[tracing::instrument(skip_all)]
28pub(crate) async fn get_1(state: State<BileState>, Path(repo_name): Path<RepoName>) -> Response {
29 state
30 .spawn(move |state| inner(&state, &repo_name, None))
31 .await
32}
33
34#[tracing::instrument(skip_all)]
35pub(crate) async fn get_2(
36 state: State<BileState>,
37 Path((repo_name, r#ref)): Path<(RepoName, Ref)>,
38) -> Response {
39 state
40 .spawn(move |state| inner(&state, &repo_name, Some(&r#ref)))
41 .await
42}
43
44fn inner(state: &BileState, repo_name: &RepoName, r#ref: Option<&Ref>) -> Result<Response> {
45 let Some(repo) = Repository::open(&state.config, repo_name).context("opening repository")?
46 else {
47 return Ok(ErrorPage::new(&state.config)
48 .with_status(StatusCode::NOT_FOUND)
49 .into_response());
50 };
51
52 if repo.is_empty()? {
53 return Ok(ErrorPage::new(&state.config)
55 .with_status(StatusCode::SERVICE_UNAVAILABLE)
56 .into_response());
57 }
58
59 let r = r#ref.map_or("HEAD", |r| r.0.as_str());
60
61 let Some(commits) = repo.commits(r, state.config.log_per_page)? else {
62 return Ok(ErrorPage::new(&state.config)
63 .with_status(StatusCode::NOT_FOUND)
64 .into_response());
65 };
66
67 let branch = repo.ref_or_head_shorthand(r#ref)?;
68
69 Ok(Xml(RepoLogFeedTemplate {
70 repo: &repo,
71 commits,
72 branch,
73 base_url: &format!("/{repo_name}"),
74 })
75 .into_response())
76}
77