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