Skip to main content

changeset_manifest/
config.rs

1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2pub enum MetadataSection {
3    Workspace,
4    Package,
5}
6
7impl std::fmt::Display for MetadataSection {
8    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9        match self {
10            Self::Workspace => f.write_str("[workspace.metadata.changeset]"),
11            Self::Package => f.write_str("[package.metadata.changeset]"),
12        }
13    }
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
17#[non_exhaustive]
18pub enum TagFormat {
19    #[default]
20    VersionOnly,
21    CratePrefixed,
22}
23
24impl TagFormat {
25    #[must_use]
26    pub const fn as_str(self) -> &'static str {
27        match self {
28            Self::VersionOnly => "version-only",
29            Self::CratePrefixed => "crate-prefixed",
30        }
31    }
32}
33
34impl std::fmt::Display for TagFormat {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        f.write_str(self.as_str())
37    }
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
41#[non_exhaustive]
42pub enum ChangelogLocation {
43    #[default]
44    Root,
45    PerPackage,
46}
47
48impl ChangelogLocation {
49    #[must_use]
50    pub const fn as_str(self) -> &'static str {
51        match self {
52            Self::Root => "root",
53            Self::PerPackage => "per-package",
54        }
55    }
56}
57
58impl std::fmt::Display for ChangelogLocation {
59    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60        f.write_str(self.as_str())
61    }
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
65#[non_exhaustive]
66pub enum ComparisonLinks {
67    #[default]
68    Auto,
69    Enabled,
70    Disabled,
71}
72
73impl ComparisonLinks {
74    #[must_use]
75    pub const fn as_str(self) -> &'static str {
76        match self {
77            Self::Auto => "auto",
78            Self::Enabled => "enabled",
79            Self::Disabled => "disabled",
80        }
81    }
82}
83
84impl std::fmt::Display for ComparisonLinks {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        f.write_str(self.as_str())
87    }
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
91#[non_exhaustive]
92pub enum ZeroVersionBehavior {
93    #[default]
94    EffectiveMinor,
95    AutoPromoteOnMajor,
96}
97
98impl ZeroVersionBehavior {
99    #[must_use]
100    pub const fn as_str(self) -> &'static str {
101        match self {
102            Self::EffectiveMinor => "effective-minor",
103            Self::AutoPromoteOnMajor => "auto-promote-on-major",
104        }
105    }
106}
107
108impl std::fmt::Display for ZeroVersionBehavior {
109    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110        f.write_str(self.as_str())
111    }
112}
113
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
115#[non_exhaustive]
116pub enum NoneBumpBehavior {
117    #[default]
118    PromoteToPatch,
119    Allow,
120    Disallow,
121}
122
123impl NoneBumpBehavior {
124    #[must_use]
125    pub const fn as_str(self) -> &'static str {
126        match self {
127            Self::PromoteToPatch => "promote-to-patch",
128            Self::Allow => "allow",
129            Self::Disallow => "disallow",
130        }
131    }
132}
133
134impl std::fmt::Display for NoneBumpBehavior {
135    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136        f.write_str(self.as_str())
137    }
138}
139
140#[derive(Debug, Clone, Default)]
141pub struct InitConfig {
142    pub commit: Option<bool>,
143    pub tags: Option<bool>,
144    pub keep_changesets: Option<bool>,
145    pub tag_format: Option<TagFormat>,
146    pub changelog: Option<ChangelogLocation>,
147    pub comparison_links: Option<ComparisonLinks>,
148    pub zero_version_behavior: Option<ZeroVersionBehavior>,
149    pub dependency_bump_changelog_template: Option<String>,
150    pub base_branch: Option<String>,
151    pub none_bump_behavior: Option<NoneBumpBehavior>,
152    pub none_bump_promote_message_template: Option<String>,
153    pub commit_title_template: Option<String>,
154    pub changes_in_body: Option<bool>,
155    pub comparison_links_template: Option<String>,
156    pub ignored_files: Option<Vec<String>>,
157}
158
159impl InitConfig {
160    #[must_use]
161    pub fn is_empty(&self) -> bool {
162        self.commit.is_none()
163            && self.tags.is_none()
164            && self.keep_changesets.is_none()
165            && self.tag_format.is_none()
166            && self.changelog.is_none()
167            && self.comparison_links.is_none()
168            && self.zero_version_behavior.is_none()
169            && self.dependency_bump_changelog_template.is_none()
170            && self.base_branch.is_none()
171            && self.none_bump_behavior.is_none()
172            && self.none_bump_promote_message_template.is_none()
173            && self.commit_title_template.is_none()
174            && self.changes_in_body.is_none()
175            && self.comparison_links_template.is_none()
176            && self.ignored_files.is_none()
177    }
178}
179
180#[cfg(test)]
181mod tests {
182    use super::*;
183
184    #[test]
185    fn is_empty_returns_false_when_only_dependency_bump_changelog_template_set() {
186        let config = InitConfig {
187            dependency_bump_changelog_template: Some(
188                "Updated dependency `{dependency}` to v{version}".to_string(),
189            ),
190            ..Default::default()
191        };
192        assert!(!config.is_empty());
193    }
194
195    #[test]
196    fn is_empty_returns_false_when_only_base_branch_set() {
197        let config = InitConfig {
198            base_branch: Some("develop".to_string()),
199            ..Default::default()
200        };
201        assert!(!config.is_empty());
202    }
203
204    #[test]
205    fn is_empty_returns_false_when_only_none_bump_behavior_set() {
206        let config = InitConfig {
207            none_bump_behavior: Some(NoneBumpBehavior::Allow),
208            ..Default::default()
209        };
210        assert!(!config.is_empty());
211    }
212
213    #[test]
214    fn is_empty_returns_false_when_only_none_bump_promote_message_template_set() {
215        let config = InitConfig {
216            none_bump_promote_message_template: Some("chore: internal changes".to_string()),
217            ..Default::default()
218        };
219        assert!(!config.is_empty());
220    }
221
222    #[test]
223    fn is_empty_returns_false_when_only_commit_title_template_set() {
224        let config = InitConfig {
225            commit_title_template: Some("{new-version}".to_string()),
226            ..Default::default()
227        };
228        assert!(!config.is_empty());
229    }
230
231    #[test]
232    fn is_empty_returns_false_when_only_changes_in_body_set() {
233        let config = InitConfig {
234            changes_in_body: Some(true),
235            ..Default::default()
236        };
237        assert!(!config.is_empty());
238    }
239
240    #[test]
241    fn is_empty_returns_false_when_only_comparison_links_template_set() {
242        let config = InitConfig {
243            comparison_links_template: Some(
244                "https://example.com/{repository}/compare/{base}...{target}".to_string(),
245            ),
246            ..Default::default()
247        };
248        assert!(!config.is_empty());
249    }
250
251    #[test]
252    fn is_empty_returns_false_when_only_ignored_files_set() {
253        let config = InitConfig {
254            ignored_files: Some(vec!["*.md".to_string()]),
255            ..Default::default()
256        };
257        assert!(!config.is_empty());
258    }
259}