wayver's git archive


a simple self-hosted git server
git clone https://git.wayver.dev/bile

src/handlers/repo_refs_feed.rs@6e060abc1f25c2e1b79fe06bfa8b72cd26952ee1

raw
Date Commit Message Author Files + -
2026-02-19 17:51 large refactoring wayverd 53 2153 1683
...

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, TagEntry},
11    http::{
12        extractor::RepoName,
13        response::{ErrorPage, Result, Xml},
14    },
15    utils::filters,
16};
17
18#[derive(askama::Template)]
19#[template(path = "refs.xml")]
20struct RepoRefFeedTemplate<'a> {
21    repo: &'a Repository,
22    tags: Vec<TagEntry>,
23    base_url: &'a str,
24}
25
26#[tracing::instrument(skip_all)]
27pub(crate) async fn get(state: State<BileState>, Path(repo_name): Path<RepoName>) -> Response {
28    state.spawn(move |state| inner(&state, &repo_name)).await
29}
30
31#[tracing::instrument(skip_all)]
32fn inner(state: &BileState, repo_name: &RepoName) -> Result<Response> {
33    let Some(repo) = Repository::open(&state.config, repo_name).context("opening repository")?
34    else {
35        return Ok(ErrorPage::new(&state.config)
36            .with_status(StatusCode::NOT_FOUND)
37            .into_response());
38    };
39
40    if repo.is_empty()? {
41        // show a server error
42        return Ok(ErrorPage::new(&state.config)
43            .with_status(StatusCode::SERVICE_UNAVAILABLE)
44            .into_response());
45    }
46
47    let mut tags = repo.tag_entries()?;
48
49    // sort so that newest tags are at the top
50    tags.sort_unstable_by(|a, b| a.signature.when().cmp(&b.signature.when()).reverse());
51
52    Ok(Xml(RepoRefFeedTemplate {
53        repo: &repo,
54        tags,
55        base_url: &format!("/{repo_name}"),
56    })
57    .into_response())
58}
59