use std::{fmt::{Display, Formatter},sync::Arc,};use askama::Template;use axum::{extract::Query,http,response::{IntoResponse, Response},Extension,};use serde::Deserialize;use crate::{git::{FileWithContent, PathDestination, TreeItem},into_response,methods::{filters,repo::{ChildPath, Repository, RepositoryPath, Result},},Git,};#[derive(Deserialize)]pub struct UriQuery {id: Option<String>,#[serde(default)]raw: bool,#[serde(rename = "h")]branch: Option<Arc<str>>,}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<TreeItem>,pub query: UriQuery,pub branch: Option<Arc<str>>,}#[derive(Template)]#[template(path = "repo/file.html")]pub struct FileView {pub repo: Repository,pub file: FileWithContent,pub branch: Option<Arc<str>>,}pub async fn handle(Extension(repo): Extension<Repository>,Extension(RepositoryPath(repository_path)): Extension<RepositoryPath>,Extension(ChildPath(child_path)): Extension<ChildPath>,Extension(git): Extension<Arc<Git>>,Query(query): Query<UriQuery>,) -> Result<Response> {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) => into_response(&TreeView {repo,items,branch: query.branch.clone(),query,}),PathDestination::File(file) if query.raw => {let headers = [(http::header::CONTENT_TYPE,http::HeaderValue::from_static("text/plain"),)];(headers, file.content).into_response()}PathDestination::File(file) => into_response(&FileView {repo,file,branch: query.branch,}),},)}