// Back - An extremely simple git issue tracking system. Inspired by tvix's // panettone // // Copyright (C) 2024 Benedikt Peetz // SPDX-License-Identifier: AGPL-3.0-or-later // // This file is part of Back. // // You should have received a copy of the License along with this program. // If not, see . use std::path::Path; use crate::{ config::BackConfig, web::issue::{Issue, Status}, }; use gix::{refs::Target, Repository}; use issue_show::BackPrefix; use rocket::{ get, response::content::{RawCss, RawHtml}, State, }; mod format; mod issue; mod issue_show; #[get("/style.css")] pub fn styles() -> RawCss { RawCss(include_str!("../../assets/style.css").to_owned()) } fn list_all_issues(repo: &'_ Repository) -> Vec> { repo.refs .iter() .expect("We should be able to iterate over references") .prefixed(Path::new("refs/bugs/")) .expect("The 'refs/bugs/' namespace should exist") .map(|val| { let reference = val.expect("'val' should be an object?"); if let Target::Object(commit_id) = reference.target { Issue::from_commit_id(repo, commit_id) } else { unreachable!("All 'refs/bugs/' should contain a clear target."); } }) .collect() } pub fn issue_list_boilerplate( config: &State, wanted_status: Status, counter_status: Status, ) -> RawHtml { let repository = &config.repository; let issue_list = list_all_issues(&repository.to_thread_local()) .iter() .fold(String::new(), |acc, val| { format!("{}{}", acc, &issue_to_string(val, wanted_status).0) }); let counter_status_lower = counter_status.to_string().to_lowercase(); RawHtml(format!( r#" Back

{wanted_status} Issues

    {issue_list}
"#, config.source_code_repository_url )) } #[get("/issues/open")] pub fn open(config: &State) -> RawHtml { issue_list_boilerplate(config, Status::Open, Status::Closed) } #[get("/issues/closed")] pub fn closed(config: &State) -> RawHtml { issue_list_boilerplate(config, Status::Closed, Status::Open) } #[get("/issue/")] pub fn show_issue(config: &State, prefix: BackPrefix) -> RawHtml { let repository = config.repository.to_thread_local(); let all_issues = list_all_issues(&repository); let maybe_issue = all_issues .iter() .find(|issue| issue.id.to_string().starts_with(&prefix.to_string())); match maybe_issue { Some(issue) => issue.to_html(config), None => RawHtml(format!("Issue with id '{prefix}' not found!")), } } fn issue_to_string(issue: &Issue<'_>, status: Status) -> RawHtml { if issue.status == status { issue.to_list_entry() } else { RawHtml(String::default()) } }