diff options
Diffstat (limited to 'pkgs/by-name/ba/back/src/web/generate/mod.rs')
-rw-r--r-- | pkgs/by-name/ba/back/src/web/generate/mod.rs | 225 |
1 files changed, 0 insertions, 225 deletions
diff --git a/pkgs/by-name/ba/back/src/web/generate/mod.rs b/pkgs/by-name/ba/back/src/web/generate/mod.rs deleted file mode 100644 index ae783a3..0000000 --- a/pkgs/by-name/ba/back/src/web/generate/mod.rs +++ /dev/null @@ -1,225 +0,0 @@ -use std::{fs, path::Path}; - -use gix::hash::Prefix; -use log::info; -use rinja::Template; -use url::Url; - -use crate::{ - config::BackConfig, - error, - git_bug::{ - dag::issues_from_repository, - issue::{CollapsedIssue, Status}, - }, -}; - -#[derive(Template)] -#[template(path = "./issues.html")] -struct IssuesTemplate { - wanted_status: Status, - counter_status: Status, - issues: Vec<CollapsedIssue>, - - /// The path to the repository - repo_path: String, - - /// The URL to `back`'s source code - source_code_repository_url: Url, -} -pub fn issues( - config: &BackConfig, - wanted_status: Status, - counter_status: Status, - repo_path: &Path, -) -> error::Result<String> { - let repository = config - .repositories()? - .get(repo_path)? - .open(&config.scan_path)?; - - let mut issue_list = issues_from_repository(&repository.to_thread_local())? - .into_iter() - .map(|issue| issue.collapse()) - .filter(|issue| issue.status == wanted_status) - .collect::<Vec<CollapsedIssue>>(); - - // Sort by date descending. - // SAFETY: - // The time stamp is only used for sorting, so a malicious attacker could only affect the issue - // sorting. - issue_list.sort_by_key(|issue| unsafe { issue.timestamp.to_unsafe() }); - issue_list.reverse(); - - Ok(IssuesTemplate { - wanted_status, - counter_status, - source_code_repository_url: config.source_code_repository_url.clone(), - issues: issue_list, - repo_path: repo_path.display().to_string(), - } - .render() - .expect("This should always work")) -} - -use crate::git_bug::format::HtmlString; -#[derive(Template)] -#[template(path = "./issue.html")] -struct IssueTemplate { - issue: CollapsedIssue, - - /// The path to the repository - repo_path: String, - - /// The URL to `back`'s source code - source_code_repository_url: Url, -} -pub fn issue(config: &BackConfig, repo_path: &Path, prefix: Prefix) -> error::Result<String> { - let repository = config - .repositories()? - .get(repo_path)? - .open(&config.scan_path)? - .to_thread_local(); - - let maybe_issue = issues_from_repository(&repository)? - .into_iter() - .map(|val| val.collapse()) - .find(|issue| issue.id.to_string().starts_with(&prefix.to_string())); - - match maybe_issue { - Some(issue) => Ok(IssueTemplate { - issue, - repo_path: repo_path.display().to_string(), - source_code_repository_url: config.source_code_repository_url.clone(), - } - .render() - .expect("This should always work")), - None => Err(error::Error::IssuesPrefixMissing { prefix }), - } -} - -#[derive(Template)] -#[template(path = "./repos.html")] -struct ReposTemplate { - repos: Vec<RepoValue>, - - /// The URL to `back`'s source code - source_code_repository_url: Url, -} -struct RepoValue { - description: String, - owner: String, - path: String, -} -pub fn repos(config: &BackConfig) -> error::Result<String> { - let repos: Vec<RepoValue> = config - .repositories()? - .iter() - .filter_map(|raw_repo| match raw_repo.open(&config.scan_path) { - Ok(repo) => { - let repo = repo.to_thread_local(); - let git_config = repo.config_snapshot(); - - let path = raw_repo.path().to_string_lossy().to_string(); - - let owner = git_config - .string("cgit.owner") - .map(|v| v.to_string()) - .unwrap_or("<No owner>".to_owned()); - - let description = fs::read_to_string(repo.git_dir().join("description")) - .unwrap_or("<No description>".to_owned()); - - Some(RepoValue { - description, - owner, - path, - }) - } - Err(err) => { - info!( - "Repo '{}' could not be opened: '{err}'", - raw_repo.path().display() - ); - None - } - }) - .collect(); - - Ok(ReposTemplate { - repos, - source_code_repository_url: config.source_code_repository_url.clone(), - } - .render() - .expect("this should work")) -} - -pub fn feed(config: &BackConfig, repo_path: &Path) -> error::Result<String> { - use rss::{ChannelBuilder, Item, ItemBuilder}; - - let repository = config - .repositories()? - .get(repo_path)? - .open(&config.scan_path)? - .to_thread_local(); - - let issues: Vec<CollapsedIssue> = issues_from_repository(&repository)? - .into_iter() - .map(|issue| issue.collapse()) - .collect(); - - // Collect all Items as rss items - let mut items: Vec<Item> = issues - .iter() - .map(|issue| { - ItemBuilder::default() - .title(issue.title.to_string()) - .author(issue.author.to_string()) - .description(issue.message.to_string()) - .pub_date(issue.timestamp.to_string()) - .link(format!( - "/{}/{}/issue/{}", - repo_path.display(), - &config.root_url, - issue.id - )) - .build() - }) - .collect(); - - // Append all comments after converting them to rss items - items.extend( - issues - .iter() - .filter(|issue| !issue.comments.is_empty()) - .flat_map(|issue| { - issue - .comments - .iter() - .map(|comment| { - ItemBuilder::default() - .title(issue.title.to_string()) - .author(comment.author.to_string()) - .description(comment.message.to_string()) - .pub_date(comment.timestamp.to_string()) - .link(format!( - "/{}/{}/issue/{}", - repo_path.display(), - &config.root_url, - issue.id - )) - .build() - }) - .collect::<Vec<Item>>() - }) - .collect::<Vec<Item>>(), - ); - - let channel = ChannelBuilder::default() - .title("Issues") - .link(config.root_url.to_string()) - .description(format!("The rss feed for issues on {}.", &config.root_url)) - .items(items) - .build(); - Ok(channel.to_string()) -} |