use std::{fs, path::Path}; use dsx_common::config::DsxConfig; use rocket_dyn_templates::{Template, context}; use serde::Serialize; use crate::{ error::ApiError, model::{DATA_DIR, PackageHandle}, }; // Search for a package #[get("/?")] pub fn search_packages(q: Option) -> Result { #[derive(Serialize)] struct Package { name: String, description: String, updated_at: String, } let mut packages = Vec::new(); let dir = match fs::read_dir(DATA_DIR.join("repos")) { Ok(dir) => dir, Err(e) => { warn!("failed to read repos directory: {}", e); return Err(ApiError::InternalServerError(())); } }; for entry in dir { let entry = entry.map_err(|e| { warn!("failed to read entry: {}", e); ApiError::InternalServerError(()) })?; let config_path = entry.path().join("repo").join("Dsx.toml"); if config_path.exists() { let text = fs::read_to_string(&config_path).map_err(|e| { warn!("failed to read config file: {}", e); ApiError::InternalServerError(()) })?; let config: DsxConfig = toml::from_str(&text).map_err(|e| { warn!("failed to parse config file: {}", e); ApiError::InternalServerError(()) })?; error!("{}", config.description.clone().unwrap_or_default()); // skip repo if it doesnt match query params if let Some(query) = &q && !(config.name.contains(query) || config .description .clone() .unwrap_or_default() .contains(query)) { continue; } packages.push(Package { name: config.name, description: config.description.unwrap_or_default(), updated_at: String::from("0:00"), }) } } Ok(Template::render( "packages", context! { packages, query: q.clone().unwrap_or_default() }, )) } // Main page for a repository, shows status, files, name etc. #[get("/")] pub fn package_main(id: &str) -> Result { // get package info let mut handle = PackageHandle::new(id); let meta = handle.get_meta()?; let config = handle.get_config()?; let files = handle.file_tree("")?; let parent_path: Option = None; let current_path: Option = None; Ok(Template::render( "package_home", context! { parent_path, current_path, meta: meta, config: config, files: files, }, )) } // Path for a file within a repo #[get("//~repo/", rank = 1)] pub fn repo_file(id: &str, path: std::path::PathBuf) -> Result { // get package info let mut handle = PackageHandle::new(id); let meta = handle.get_meta()?; let config = handle.get_config()?; let files = handle.file_tree(&path)?; let parent_path = path.parent().unwrap_or(Path::new("")); let current_path = &path; Ok(Template::render( "package_home", context! { parent_path, current_path, meta: meta, config: config, files: files, }, )) } // Search within a package's files #[get("//~repo?", rank = 2)] pub fn search_repo_files(name: &str, q: Option) -> String { format!("Search within {} for {:?}", name, q) } // Page listing repo artifacts by date #[get("//artifacts")] pub fn list_artifacts(name: &str) -> String { format!("Artifacts for package {}", name) } // Page for a specific artifact and status/logs #[get("//artifacts/")] pub fn artifact_detail(name: &str, id: u64) -> String { format!("Artifact {} details for package {}", id, name) }