wayver's git archive


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

src/handlers/repo_refs.rs@1160e836ead3fbd29e297268d1009d648b68cae0

raw
Date Commit Message Author Files + -
2026-02-20 20:25 remove unneeded result type alias wayverd 13 27 31
...

1use axum::{
2    extract::State,
3    http::StatusCode,
4    response::{IntoResponse as _, Response},
5};
6
7use crate::{
8    BileState,
9    config::Config,
10    error::{Context as _, Result},
11    git::{Repository, TagEntry},
12    http::{
13        extractor::RepoName,
14        path::Path,
15        response::{ErrorPage, Html, Redirect},
16    },
17    utils::filters,
18};
19
20#[derive(askama::Template)]
21#[template(path = "refs.html")]
22struct RepoRefTemplate<'a> {
23    config: &'a Config,
24    repo: &'a Repository,
25    branches: Vec<git2::Reference<'a>>,
26    tags: Vec<TagEntry>,
27}
28
29#[tracing::instrument(skip_all)]
30pub(crate) async fn get(state: State<BileState>, Path(repo_name): Path<RepoName>) -> Response {
31    state.spawn(move |state| inner(&state, &repo_name)).await
32}
33
34#[tracing::instrument(skip_all)]
35fn inner(state: &BileState, repo_name: &RepoName) -> Result<Response> {
36    let Some(repo) = Repository::open(&state.config, repo_name).context("opening repository")?
37    else {
38        return Ok(ErrorPage::from(state)
39            .with_status(StatusCode::NOT_FOUND)
40            .into_response());
41    };
42
43    if repo.is_empty()? {
44        return Ok(Redirect::permanent(&format!("/{repo_name}"))
45            .unwrap_or(Redirect::PERMANENT_ROOT)
46            .into_response());
47    }
48
49    let branches = repo.branches()?;
50
51    let mut tags = repo.tag_entries()?;
52
53    // sort so that newest tags are at the top
54    tags.sort_unstable_by(|a, b| a.signature.when().cmp(&b.signature.when()).reverse());
55
56    Ok(Html(RepoRefTemplate {
57        config: &state.config,
58        repo: &repo,
59        branches,
60        tags,
61    })
62    .into_response())
63}
64