diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2024-12-26 17:50:54 +0100 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2024-12-26 17:58:27 +0100 |
commit | dfb5714045e99a09bf3f67890ae3cdeab47058b3 (patch) | |
tree | 5e76e310892ea7e36099312e25023aa154217a28 /pkgs/by-name/ba/back/src/web/mod.rs | |
parent | fix(pkgs/back): Use rocket to manage the configuration values (diff) | |
download | nixos-server-dfb5714045e99a09bf3f67890ae3cdeab47058b3.zip |
feat(pkgs/back): Rewrite the `git-bug` interface code
The previous code was more or less reverse engineered, whilst this code is based on the actually git-bug source code. This improves the whole issue and operation handling immensely and also makes the code better maintainable. Furthermore, it also adds support for the operations that had not already used in `vhack.eu/nixos-server.git`.
Diffstat (limited to 'pkgs/by-name/ba/back/src/web/mod.rs')
-rw-r--r-- | pkgs/by-name/ba/back/src/web/mod.rs | 148 |
1 files changed, 72 insertions, 76 deletions
diff --git a/pkgs/by-name/ba/back/src/web/mod.rs b/pkgs/by-name/ba/back/src/web/mod.rs index ed91e7e..1e6a5af 100644 --- a/pkgs/by-name/ba/back/src/web/mod.rs +++ b/pkgs/by-name/ba/back/src/web/mod.rs @@ -9,125 +9,121 @@ // You should have received a copy of the License along with this program. // If not, see <https://www.gnu.org/licenses/agpl.txt>. -use std::path::Path; - use crate::{ config::BackConfig, - web::issue::{Issue, Status}, + error::{self, Error}, + git_bug::{ + dag::issues_from_repository, + issue::{CollapsedIssue, Status}, + }, }; -use gix::{refs::Target, Repository}; -use issue_show::BackPrefix; +use prefix::BackPrefix; use rocket::{ get, response::content::{RawCss, RawHtml}, State, }; -mod format; -mod issue; -mod issue_show; +mod issue_html; +pub mod prefix; #[get("/style.css")] pub fn styles() -> RawCss<String> { RawCss(include_str!("../../assets/style.css").to_owned()) } -fn list_all_issues(repo: &'_ Repository) -> Vec<Issue<'_>> { - 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<BackConfig>, wanted_status: Status, counter_status: Status, -) -> RawHtml<String> { +) -> error::Result<RawHtml<String>> { let repository = &config.repository; - let issue_list = list_all_issues(&repository.to_thread_local()) - .iter() + let issue_list = issues_from_repository(&repository.to_thread_local())? + .into_iter() .fold(String::new(), |acc, val| { - format!("{}{}", acc, &issue_to_string(val, wanted_status).0) + let issue = val.collaps(); + + format!("{}{}", acc, { + if issue.status == wanted_status { + let issue_entry = issue.to_list_entry(); + issue_entry.0 + } else { + String::new() + } + }) }); let counter_status_lower = counter_status.to_string().to_lowercase(); - RawHtml(format!( + Ok(RawHtml(format!( r#" -<!DOCTYPE html> -<html lang="en"> - <head> - <title>Back</title> - <link href="/style.css" rel="stylesheet" type="text/css"> - <meta content="width=device-width,initial-scale=1" name="viewport"> - </head> - <body> - <div class="content"> - <header> - <h1>{wanted_status} Issues</h1> - </header> - <main> - <div class="issue-links"> - <a href="/issues/{counter_status_lower}/">View {counter_status} issues</a> - <a href="{}">Source code</a> - <!-- - <form class="issue-search" method="get"> - <input name="search" title="Issue search query" type="search"> - <input class="sr-only" type="submit" value="Search Issues"> - </form> - --> - </div> - <ol class="issue-list"> - {issue_list} - </ol> - </main> - </div> - </body> -</html> -"#, + <!DOCTYPE html> + <html lang="en"> + <head> + <title>Back</title> + <link href="/style.css" rel="stylesheet" type="text/css"> + <meta content="width=device-width,initial-scale=1" name="viewport"> + </head> + <body> + <div class="content"> + <header> + <h1>{wanted_status} Issues</h1> + </header> + <main> + <div class="issue-links"> + <a href="/issues/{counter_status_lower}/">View {counter_status} issues</a> + <a href="{}">Source code</a> + <!-- + <form class="issue-search" method="get"> + <input name="search" title="Issue search query" type="search"> + <input class="sr-only" type="submit" value="Search Issues"> + </form> + --> + </div> + <ol class="issue-list"> + {issue_list} + </ol> + </main> + </div> + </body> + </html> + "#, config.source_code_repository_url - )) + ))) } #[get("/issues/open")] -pub fn open(config: &State<BackConfig>) -> RawHtml<String> { +pub fn open(config: &State<BackConfig>) -> error::Result<RawHtml<String>> { issue_list_boilerplate(config, Status::Open, Status::Closed) } #[get("/issues/closed")] -pub fn closed(config: &State<BackConfig>) -> RawHtml<String> { +pub fn closed(config: &State<BackConfig>) -> error::Result<RawHtml<String>> { issue_list_boilerplate(config, Status::Closed, Status::Open) } #[get("/issue/<prefix>")] -pub fn show_issue(config: &State<BackConfig>, prefix: BackPrefix) -> RawHtml<String> { +pub fn show_issue( + config: &State<BackConfig>, + prefix: Result<BackPrefix, gix::hash::prefix::from_hex::Error>, +) -> error::Result<RawHtml<String>> { + // NOTE(@bpeetz): Explicitly unwrap the `prefix` here (instead of taking the unwrapped value as + // argument), to avoid triggering rockets "errors forward to the next route" feature. + // This ensures, that our error message actually reaches the user. <2024-12-26> + let prefix = prefix?; + let repository = config.repository.to_thread_local(); - let all_issues = list_all_issues(&repository); + let all_issues: Vec<CollapsedIssue> = issues_from_repository(&repository)? + .into_iter() + .map(|val| val.collapse()) + .collect(); + 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<String> { - if issue.status == status { - issue.to_list_entry() - } else { - RawHtml(String::default()) + Some(issue) => Ok(issue.to_html(config)), + None => Err(Error::IssuesPrefixMissing { prefix }), } } |