use std::{ fmt::{Display, Formatter}, sync::Arc, }; use askama::Template; use axum::{extract::Query, response::IntoResponse, Extension}; use serde::Deserialize; use crate::{ git::{FileWithContent, PathDestination, TreeItem}, into_response, methods::{ filters, repo::{ChildPath, Repository, RepositoryPath, Result}, }, Git, ResponseEither, }; #[derive(Deserialize)] pub struct UriQuery { id: Option, #[serde(default)] raw: bool, #[serde(rename = "h")] branch: Option>, } impl Display for UriQuery { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let mut prefix = "?"; if let Some(id) = self.id.as_deref() { write!(f, "{prefix}id={id}")?; prefix = "&"; } if let Some(branch) = self.branch.as_deref() { write!(f, "{prefix}h={branch}")?; } Ok(()) } } #[derive(Template)] #[template(path = "repo/tree.html")] #[allow(clippy::module_name_repetitions)] pub struct TreeView { pub repo: Repository, pub items: Vec, pub query: UriQuery, pub branch: Option>, } #[derive(Template)] #[template(path = "repo/file.html")] pub struct FileView { pub repo: Repository, pub file: FileWithContent, pub branch: Option>, } pub async fn handle( Extension(repo): Extension, Extension(RepositoryPath(repository_path)): Extension, Extension(ChildPath(child_path)): Extension, Extension(git): Extension>, Query(query): Query, ) -> Result { let open_repo = git.repo(repository_path, query.branch.clone()).await?; Ok( match open_repo .path(child_path, query.id.as_deref(), !query.raw) .await? { PathDestination::Tree(items) => { ResponseEither::Left(ResponseEither::Left(into_response(TreeView { repo, items, branch: query.branch.clone(), query, }))) } PathDestination::File(file) if query.raw => ResponseEither::Right(file.content), PathDestination::File(file) => { ResponseEither::Left(ResponseEither::Right(into_response(FileView { repo, file, branch: query.branch, }))) } }, ) }