wayver's git archive


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

src/handlers/repo_refs_feed.rs@f3f2b40f0ffae5de2e6d3f661e32b582274bae49

raw
Date Commit Message Author Files + -
2026-02-17 21:07 initial mvp wayverd 74 10800 0
...

1use axum::{
2    extract::Path,
3    http::StatusCode,
4    response::{IntoResponse as _, Response},
5};
6
7use crate::utils::{
8    Error, Result,
9    error::Context as _,
10    extractor::repo_name_checks,
11    filters,
12    git::{Repository, TagEntry},
13    response::Xml,
14    spawn_blocking,
15};
16
17#[derive(askama::Template)]
18#[template(path = "refs.xml")]
19struct RepoRefFeedTemplate<'a> {
20    repo: &'a Repository,
21    tags: Vec<TagEntry>,
22    base_url: &'a str,
23}
24
25#[tracing::instrument(skip_all)]
26pub async fn get(Path(repo_name): Path<String>) -> Response {
27    spawn_blocking(move || inner(&repo_name).into_response()).await
28}
29
30#[tracing::instrument(skip_all)]
31fn inner(repo_name: &str) -> Result {
32    repo_name_checks(repo_name)?;
33
34    let Some(repo) = Repository::open(repo_name).context("opening repository")? else {
35        return Err(Error::new(StatusCode::NOT_FOUND, "repo does not exist"));
36    };
37
38    if repo.is_empty()? {
39        // show a server error
40        return Err(Error::new(
41            StatusCode::SERVICE_UNAVAILABLE,
42            "Cannot show feed because there is nothing here.",
43        ));
44    }
45
46    let mut tags = repo.tag_entries()?;
47
48    // sort so that newest tags are at the top
49    tags.sort_unstable_by(|a, b| a.signature.when().cmp(&b.signature.when()).reverse());
50
51    Ok(Xml(RepoRefFeedTemplate {
52        repo: &repo,
53        tags,
54        base_url: &format!("/{repo_name}"),
55    })
56    .into_response())
57}
58