gitscope
← rgit / 0.1.4 / src/methods/repo/tree.rs
https://dev.kronoz.win/r/rgit.git
src/methods/repo/tree.rs · Rust
Blame Raw
  1use askama::Template;
  2use axum::{extract::Query, response::IntoResponse, Extension};
  3use itertools::Itertools;
  4use serde::Deserialize;
  5use std::path::PathBuf;
  6use std::{
  7    fmt::{Display, Formatter},
  8    sync::Arc,
  9};
 10
 11use crate::{
 12    git::{FileWithContent, PathDestination, TreeItem},
 13    into_response,
 14    methods::{
 15        filters,
 16        repo::{ChildPath, Repository, RepositoryPath, Result},
 17    },
 18    Git, ResponseEither,
 19};
 20
 21#[derive(Deserialize)]
 22pub struct UriQuery {
 23    id: Option<String>,
 24    #[serde(default)]
 25    raw: bool,
 26    #[serde(rename = "h")]
 27    branch: Option<Arc<str>>,
 28}
 29
 30impl Display for UriQuery {
 31    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
 32        let mut prefix = "?";
 33
 34        if let Some(id) = self.id.as_deref() {
 35            write!(f, "{prefix}id={id}")?;
 36            prefix = "&";
 37        }
 38
 39        if let Some(branch) = self.branch.as_deref() {
 40            write!(f, "{prefix}h={branch}")?;
 41        }
 42
 43        Ok(())
 44    }
 45}
 46
 47#[derive(Template)]
 48#[template(path = "repo/tree.html")]
 49#[allow(clippy::module_name_repetitions)]
 50pub struct TreeView {
 51    pub repo: Repository,
 52    pub items: Vec<TreeItem>,
 53    pub query: UriQuery,
 54    pub repo_path: PathBuf,
 55    pub branch: Option<Arc<str>>,
 56}
 57
 58#[derive(Template)]
 59#[template(path = "repo/file.html")]
 60pub struct FileView {
 61    pub repo: Repository,
 62    pub repo_path: PathBuf,
 63    pub file: FileWithContent,
 64    pub branch: Option<Arc<str>>,
 65}
 66
 67pub async fn handle(
 68    Extension(repo): Extension<Repository>,
 69    Extension(RepositoryPath(repository_path)): Extension<RepositoryPath>,
 70    Extension(ChildPath(child_path)): Extension<ChildPath>,
 71    Extension(git): Extension<Arc<Git>>,
 72    Query(query): Query<UriQuery>,
 73) -> Result<impl IntoResponse> {
 74    let open_repo = git.repo(repository_path, query.branch.clone()).await?;
 75
 76    Ok(
 77        match open_repo
 78            .path(child_path.clone(), query.id.as_deref(), !query.raw)
 79            .await?
 80        {
 81            PathDestination::Tree(items) => {
 82                ResponseEither::Left(ResponseEither::Left(into_response(TreeView {
 83                    repo,
 84                    items,
 85                    branch: query.branch.clone(),
 86                    query,
 87                    repo_path: child_path.unwrap_or_default(),
 88                })))
 89            }
 90            PathDestination::File(file) if query.raw => ResponseEither::Right(file.content),
 91            PathDestination::File(file) => {
 92                ResponseEither::Left(ResponseEither::Right(into_response(FileView {
 93                    repo,
 94                    file,
 95                    branch: query.branch,
 96                    repo_path: child_path.unwrap_or_default(),
 97                })))
 98            }
 99        },
100    )
101}