repos
/ repos-rust master

repos-rust

mirror archived upstream

A minimal self-hosted git browser on Rust axum: bare repos rendered as a website with commits, diffs, syntax-highlighted blobs, atom feeds, and clone over HTTPS.

axumdockergitgit-browsergitoxidegixrustself-hosted

1.7 KB · 51 lines · Rust Raw History
 1use axum::{
 2    extract::{Path, State},
 3    response::{IntoResponse, Response},
 4    routing::get,
 5    Router,
 6};
 7
 8use crate::render::{not_found, render};
 9use crate::AppState;
10
11pub fn router() -> Router<AppState> {
12    Router::new().route("/{name}/commit/{sha}", get(commit_page))
13}
14
15async fn commit_page(
16    Path((name, sha)): Path<(String, String)>,
17    State(state): State<AppState>,
18) -> Response {
19    let repo_root = state.config.repo_root.clone();
20    let clone_base = state.config.clone_base.clone();
21    let name_for_blocking = name.clone();
22    let sha_for_blocking = sha.clone();
23    let result = tokio::task::spawn_blocking(move || -> anyhow::Result<_> {
24        let repo_path = crate::git::resolve_path(&repo_root, &name_for_blocking)?;
25        let repo = crate::git::open(&repo_root, &name_for_blocking)?;
26        let summary = crate::git::repo_summary(&repo_path, &clone_base)?;
27        let oid = crate::git::resolve_rev(&repo, &sha_for_blocking)?;
28        let commit = crate::git::commit_info(&repo, oid)?;
29        let files = crate::git::diff_commit(&repo_path, oid)?;
30        Ok((summary, commit, files))
31    })
32    .await;
33    match result {
34        Ok(Ok((summary, commit, files))) => render(
35            &state,
36            "commit.html",
37            &format!("/{name}/commit/{sha}"),
38            minijinja::context! {
39                repo => &summary,
40                commit => &commit,
41                files => &files,
42            },
43        ),
44        Ok(Err(e)) => not_found(&state, &name, e),
45        Err(e) => {
46            tracing::error!("commit_page join: {e}");
47            (axum::http::StatusCode::INTERNAL_SERVER_ERROR, "render error").into_response()
48        }
49    }
50}