wayver's git archive


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

src/handlers/repo_file_raw.rs@71b17dd92232913d023854951d629e9876076719

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

1use std::path;
2
3use axum::{
4    extract::State,
5    http::{StatusCode, header},
6    response::{IntoResponse as _, Response},
7};
8
9use crate::{
10    BileState,
11    error::{Context as _, Result},
12    git::Repository,
13    http::{
14        extractor::{ObjectName, Ref, RepoName},
15        path::Path,
16        response::ErrorPage,
17    },
18    utils::blob_mime,
19};
20
21#[tracing::instrument(skip_all)]
22pub(crate) async fn get(
23    state: State<BileState>,
24    Path((repo_name, r#ref, object_name)): Path<(RepoName, Ref, ObjectName)>,
25) -> Response {
26    state
27        .spawn(move |state| inner(&state, &repo_name, &r#ref, &object_name))
28        .await
29}
30
31#[tracing::instrument(skip_all)]
32fn inner(
33    state: &BileState,
34    repo_name: &RepoName,
35    r#ref: &Ref,
36    object_name: &ObjectName,
37) -> Result<Response> {
38    let repo = match Repository::open(&state.config, repo_name).context("opening repository") {
39        Ok(Some(repo)) => repo,
40        Ok(None) => {
41            return Ok(ErrorPage::from(state)
42                .with_status(StatusCode::NOT_FOUND)
43                .into_response());
44        }
45        Err(err) => {
46            tracing::error!(err=?err, "failed to open repository");
47
48            return Ok(ErrorPage::from(state)
49                .with_status(StatusCode::NOT_FOUND)
50                .into_response());
51        }
52    };
53
54    let path = path::Path::new(&object_name.0);
55
56    let Some((_, tree)) = repo
57        .commit_tree(&r#ref.0)
58        .context("failed to get commit tree")?
59    else {
60        return Ok(ErrorPage::from(state)
61            .with_status(StatusCode::NOT_FOUND)
62            .into_response());
63    };
64
65    let Some(blob) = repo.tree_blob(&tree, path)? else {
66        return Ok(ErrorPage::from(state)
67            .with_status(StatusCode::NOT_FOUND)
68            .into_response());
69    };
70
71    let extension = path
72        .extension()
73        .and_then(std::ffi::OsStr::to_str)
74        .unwrap_or_default();
75
76    let mime = blob_mime(&blob, extension);
77
78    Ok((
79        StatusCode::OK,
80        [(header::CONTENT_TYPE, mime.as_ref())],
81        blob.content().to_vec(),
82    )
83        .into_response())
84}
85