From 7b60f34e6df6a932adf5628cd6054e1c1f564e17 Mon Sep 17 00:00:00 2001 From: Hannes De Valkeneer <2261239+hdevalke@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:23:45 +0200 Subject: [PATCH] fix: normalize footer `BREAKING CHANGE` and `BREAKING-CHANGE` to avoid duplicate header in changelog Refs: #222 --- src/cmd/changelog.rs | 6 +++--- src/conventional.rs | 2 +- src/conventional/commits.rs | 42 +++++++++++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/cmd/changelog.rs b/src/cmd/changelog.rs index 66302f7..19ff5f8 100644 --- a/src/cmd/changelog.rs +++ b/src/cmd/changelog.rs @@ -13,7 +13,7 @@ use crate::{ Note, NoteGroup, Reference, }, config::Config, - CommitParser, Footer, + CommitParser, Footer, FooterKey, }, git::{filter_merge_commits, GitHelper, VersionAndTag}, semver::SemVer, @@ -102,10 +102,10 @@ impl<'a> ChangeLogTransformer<'a> { fn make_notes(&self, footers: &'a [Footer], scope: Option) -> Vec<(String, Note)> { footers .iter() - .filter(|footer| footer.key.starts_with("BREAKING")) + .filter(|footer| matches!(footer.key, FooterKey::BreakingChange)) .map(|footer| { ( - footer.key.clone(), + footer.key.to_string(), Note { scope: scope.clone(), text: footer.value.clone(), diff --git a/src/conventional.rs b/src/conventional.rs index 74d1ed8..7c69dd7 100644 --- a/src/conventional.rs +++ b/src/conventional.rs @@ -23,5 +23,5 @@ pub(crate) mod changelog; mod commits; pub(crate) mod config; -pub(crate) use commits::{CommitParser, Footer, ParseError}; +pub(crate) use commits::{CommitParser, Footer, FooterKey, ParseError}; pub(crate) use config::Config; diff --git a/src/conventional/commits.rs b/src/conventional/commits.rs index 20fb1be..02a1a67 100644 --- a/src/conventional/commits.rs +++ b/src/conventional/commits.rs @@ -1,4 +1,4 @@ -use std::fmt; +use std::fmt::{self, Display}; use regex::Regex; use serde::Serialize; @@ -6,10 +6,34 @@ use thiserror::Error; #[derive(Debug, PartialEq)] pub(crate) struct Footer { - pub(crate) key: String, + pub(crate) key: FooterKey, pub(crate) value: String, } +#[derive(Debug, PartialEq)] +pub(crate) enum FooterKey { + BreakingChange, + String(String), +} + +impl From<&str> for FooterKey { + fn from(value: &str) -> Self { + match value { + "BREAKING CHANGE" | "BREAKING-CHANGE" => Self::BreakingChange, + _ => Self::String(value.to_owned()), + } + } +} + +impl Display for FooterKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + FooterKey::BreakingChange => write!(f, "BREAKING CHANGE"), + FooterKey::String(s) => write!(f, "{}", s), + } + } +} + #[derive(Debug, PartialEq, Serialize)] pub(crate) struct Reference { pub(crate) action: Option, @@ -34,7 +58,7 @@ impl Commit { || self .footers .iter() - .any(|f| f.key == "BREAKING CHANGE" || f.key == "BREAKING-CHANGE") + .any(|f| matches!(f.key, FooterKey::BreakingChange)) } } @@ -110,13 +134,13 @@ impl CommitParser { match (key, ref_key, value) { (Some(key), None, Some(value)) => { footers.push(Footer { - key: key.to_owned(), + key: key.into(), value: value.to_owned(), }); } (None, Some(key), Some(value)) => { footers.push(Footer { - key: key.to_owned(), + key: key.into(), value: value.to_owned(), }); } @@ -132,7 +156,7 @@ impl CommitParser { for captures in self.regex_references.captures_iter(line) { let prefix = &captures[1]; let issue = &captures[2]; - let action = footers.last().map(|footer| footer.key.to_owned()); + let action = footers.last().map(|footer| footer.key.to_string()); let reference = Reference { action, prefix: prefix.into(), @@ -352,7 +376,7 @@ mod tests { description: "allow provided config object to extend other configs".into(), body: None, footers: vec![Footer { - key: "BREAKING CHANGE".to_string(), + key: FooterKey::BreakingChange, value: "`extends` key in config file is now used for extending other config files" .to_string() @@ -406,11 +430,11 @@ mod tests { body: Some("see the issue for details\n\non typos fixed.".into()), footers: vec![ Footer { - key: "Reviewed-by".to_string(), + key: FooterKey::String("Reviewed-by".into()), value: "Z".to_string() }, Footer { - key: "Refs".to_string(), + key: "Refs".into(), value: "133".to_string() } ],