diff --git a/src/changelog/mod.rs b/src/changelog/mod.rs index d72b178..87840da 100644 --- a/src/changelog/mod.rs +++ b/src/changelog/mod.rs @@ -49,7 +49,7 @@ struct PullRequest { commits: Vec, } -pub fn get_changelog(verbose: bool, start_revision: &str, end_revision: &str, milestone: &str, repository: &str, dir: &str) -> Result { +pub fn get_changelog(verbose: bool, start_revision: &str, end_revision: &str, milestone: &str, repository: &str, dir: &str, exclude_pr: &[String]) -> Result { if verbose { println!("\nCOMMANDS"); println!("{SEPARATOR_LINE}"); @@ -99,6 +99,10 @@ pub fn get_changelog(verbose: bool, start_revision: &str, end_revision: &str, mi // Move all pull requests to sorted map. let mut pull_request_map = BTreeMap::new(); for pull_request in &pull_requests { + // Skip pull requests that match any exclusion pattern. + if exclude_pr.iter().any(|pattern| pull_request.title.contains(pattern)) { + continue; + } // From commit map remove commits that are included in pull request. for commit in &pull_request.commits { commit_map.remove(&commit.hash); diff --git a/src/cli.rs b/src/cli.rs index d521a42..255edfd 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -29,6 +29,8 @@ enum Action { String, /// Verbose flag. bool, + /// Exclude PR patterns. + Vec, ), /// Do nothing. Nothing, @@ -109,6 +111,14 @@ fn get_matches() -> ArgMatches { .default_value("false") .default_missing_value("true") .display_order(6), + ) + .arg( + Arg::new("exclude-pr") + .long("exclude-pr") + .help("Exclude pull requests that contain this string in title") + .action(ArgAction::Append) + .num_args(1) + .display_order(7), ), ) .get_matches() @@ -141,7 +151,8 @@ fn get_cli_action() -> Action { let repository = match_string(matches, "repository"); let dir = match_string(matches, "directory"); let verbose = match_boolean(matches, "verbose"); - return Action::Changelog(start_revision, end_revision, milestone, repository, dir, verbose); + let exclude_pr = match_string_vec(matches, "exclude-pr"); + return Action::Changelog(start_revision, end_revision, milestone, repository, dir, verbose, exclude_pr); } _ => {} } @@ -163,8 +174,8 @@ pub fn do_action() { Action::CodeOfConduct => { utils::write_file("CODE_OF_CONDUCT.md", &get_code_of_conduct()); } - Action::Changelog(start_revision, end_revision, milestone, repository, dir, verbose) => { - match get_changelog(verbose, &start_revision, &end_revision, &milestone, &repository, &dir) { + Action::Changelog(start_revision, end_revision, milestone, repository, dir, verbose, exclude_pr) => { + match get_changelog(verbose, &start_revision, &end_revision, &milestone, &repository, &dir, &exclude_pr) { Ok(changelog) => { println!("\nCHANGELOG"); println!("{SEPARATOR_LINE}"); @@ -190,3 +201,8 @@ fn match_string(matches: &ArgMatches, name: &str) -> String { fn match_boolean(matches: &ArgMatches, name: &str) -> bool { matches.get_flag(name) } + +/// Matches an optional repeatable string argument. +fn match_string_vec(matches: &ArgMatches, name: &str) -> Vec { + matches.get_many::(name).map(|values| values.cloned().collect()).unwrap_or_default() +}