pub enum IssueRelated { OpenProjectIssue(String), } pub fn append_related_issues(issue: &IssueRelated, content: &String) -> String { let mut splitted = content.lines(); let mut new_content: Vec = Vec::new(); let mut found = false; let mut iteration_started = false; while let Some(line) = splitted.next() { if line.contains("## Related issues") { found = true; new_content.push(line.parse().unwrap()); // we go to the end of the section while let Some(line) = splitted.next() { if line.starts_with("-") || line.starts_with("*") { iteration_started = true; new_content.push(line.parse().unwrap()); } else if (line.trim().is_empty()) && iteration_started { new_content.append(&mut add_related_issues_section(issue)); iteration_started = false; found = true; new_content.push(line.parse().unwrap()); break; } else if line.starts_with("#") { new_content.push("new title found".to_string()); found = true; new_content.append(&mut add_related_issues_section(issue)); new_content.push("".to_string()); new_content.push(line.parse().unwrap()); break; } else { new_content.push(line.parse().unwrap()); } } } else { new_content.push(line.parse().unwrap()); } } if !found || iteration_started { if !found { new_content.append(&mut add_related_issues_title()); } new_content.append(&mut add_related_issues_section(issue)); } new_content.join(&"\n") } fn add_related_issues_title() -> Vec { let mut previous: Vec = Vec::new(); previous.push("".to_string()); previous.push("## Related issues".to_string()); previous.push("".to_string()); previous } fn add_related_issues_section(issue: &IssueRelated) -> Vec { let mut previous: Vec = Vec::new(); previous.push(convert_issue_link_items(issue)); previous } fn convert_issue_link_items(issue: &IssueRelated) -> String { match issue { IssueRelated::OpenProjectIssue(issue_url) => format!("- [{}]({})", issue_url, issue_url), } } #[cfg(test)] mod tests { use crate::planning::utils::{append_related_issues, IssueRelated}; #[test] pub fn test_append_related_issues_content_empty() { let issue = IssueRelated::OpenProjectIssue("https://example/wp/1".to_string()); assert_eq!( r#" ## Related issues - [https://example/wp/1](https://example/wp/1)"#, append_related_issues(&issue, &("".to_string())) ); } #[test] pub fn test_append_related_issues_content_not_empty() { let issue = IssueRelated::OpenProjectIssue("https://example/wp/1".to_string()); assert_eq!( r#"Something happens. ## Some title Some content ## Related issues - [https://example/wp/1](https://example/wp/1)"#, append_related_issues( &issue, &"Something happens.\n\ \n\ ## Some title\n\ \n\ Some content" .to_string() ), ); } #[test] pub fn test_append_related_issues_existing_section_related_issues() { let issue = IssueRelated::OpenProjectIssue("https://example/wp/1".to_string()); assert_eq!( r#"Something happens. ## Some title Some content ## Related issues - [https://example/wp/2](https://example/wp/2) - [https://example/wp/1](https://example/wp/1)"#, append_related_issues( &issue, &r#"Something happens. ## Some title Some content ## Related issues - [https://example/wp/2](https://example/wp/2)"# .to_string() ), ); } #[test] pub fn test_append_related_issues_existing_section_related_issues_not_last() { let issue = IssueRelated::OpenProjectIssue("https://example/wp/1".to_string()); assert_eq!( r#"Something happens. ## Some title Some content ## Related issues - [https://example/wp/2](https://example/wp/2) - [https://example/wp/1](https://example/wp/1) ## Other content Some other content"#, append_related_issues( &issue, &r#"Something happens. ## Some title Some content ## Related issues - [https://example/wp/2](https://example/wp/2) ## Other content Some other content"# .to_string() ), ); } }