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