use clap::ValueEnum;
use serde::{Deserialize, Serialize};
use strum::AsRefStr;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChangelogEntry {
pub version: String,
pub date: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub notes: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub added: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub changed: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub deprecated: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub removed: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub fixed: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub security: Vec<String>,
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize, AsRefStr, ValueEnum,
)]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
pub enum ChangelogCategory {
#[default]
Added,
Changed,
Deprecated,
Removed,
Fixed,
Security,
Chore,
}
impl ChangelogCategory {
pub const VALID_PREFIXES: &'static [&'static str] = &[
"add",
"fix",
"change",
"remove",
"deprecate",
"security",
"chore",
];
pub const RELEASE_CHANGELOG_SECTIONS: &'static [(Self, &'static str)] = &[
(Self::Added, "Added"),
(Self::Changed, "Changed"),
(Self::Deprecated, "Deprecated"),
(Self::Removed, "Removed"),
(Self::Fixed, "Fixed"),
(Self::Security, "Security"),
];
pub fn from_prefix(prefix: &str) -> Option<Self> {
match prefix.to_lowercase().as_str() {
"add" | "added" | "feat" | "feature" => Some(Self::Added),
"changed" | "change" | "refactor" | "perf" => Some(Self::Changed),
"deprecated" | "deprecate" => Some(Self::Deprecated),
"removed" | "remove" => Some(Self::Removed),
"fix" | "fixed" => Some(Self::Fixed),
"security" | "sec" => Some(Self::Security),
"chore" | "internal" | "test" | "tests" | "doc" | "docs" | "ci" | "build" => {
Some(Self::Chore)
}
_ => None,
}
}
pub fn from_rendered_prefix(prefix: &str) -> Option<Self> {
match prefix.to_lowercase().as_str() {
"added" => Some(Self::Added),
"changed" => Some(Self::Changed),
"deprecated" => Some(Self::Deprecated),
"removed" => Some(Self::Removed),
"fixed" => Some(Self::Fixed),
"security" => Some(Self::Security),
"chore" => Some(Self::Chore),
_ => None,
}
}
pub fn strip_rendered_prefix(text: &str) -> Option<&str> {
let (prefix, rest) = text.split_once(':')?;
Self::from_rendered_prefix(prefix).map(|_| rest.trim_start())
}
}