1use crate::release::Release;
2use std::collections::BTreeMap;
3
4#[derive(Debug, Clone, Default)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct Changelog {
8 pub(crate) title: String,
9 pub(crate) description: Option<String>,
10 releases: BTreeMap<Option<semver::Version>, Release>,
11 pub(crate) keep_a_changelog_message: bool,
12 pub(crate) semantic_versioning_message: bool,
13}
14
15impl Changelog {
16 pub fn new(title: impl ToString) -> Self {
18 Self {
19 title: title.to_string(),
20 description: None,
21 releases: Default::default(),
22 keep_a_changelog_message: false,
23 semantic_versioning_message: false,
24 }
25 }
26
27 pub fn with_description(self, description: impl ToString) -> Self {
29 Self {
30 description: Some(description.to_string()),
31 ..self
32 }
33 }
34
35 pub fn add_release(self, release: Release) -> Self {
37 let mut releases = self.releases;
38 releases.insert(release.version.clone(), release);
39
40 Self { releases, ..self }
41 }
42
43 pub fn add_keep_a_changelog_message(self) -> Self {
45 Self {
46 keep_a_changelog_message: true,
47 ..self
48 }
49 }
50
51 pub fn add_semantic_versioning_message(self) -> Self {
53 Self {
54 semantic_versioning_message: true,
55 ..self
56 }
57 }
58
59 pub fn releases(&self) -> impl Iterator<Item = &Release> {
61 self.releases.values()
62 }
63
64 pub fn versions(&self) -> impl Iterator<Item = &semver::Version> {
67 self.releases.keys().filter_map(|v| v.as_ref())
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn ensure_releases_are_sorted_by_version_number() {
77 let changelog = Changelog::new("")
78 .add_release(Release::new(0, 2, 0))
79 .add_release(Release::new(0, 1, 0))
80 .add_release(Release::new(0, 1, 1))
81 .add_release(Release::unreleased())
82 .add_release(Release::new(0, 2, 1))
83 .add_release(Release::new(0, 1, 2));
84
85 assert_eq!(
86 changelog
87 .releases()
88 .map(|v| v.version.clone())
89 .collect::<Vec<_>>(),
90 vec![
91 None,
92 Some(semver::Version::new(0, 1, 0)),
93 Some(semver::Version::new(0, 1, 1)),
94 Some(semver::Version::new(0, 1, 2)),
95 Some(semver::Version::new(0, 2, 0)),
96 Some(semver::Version::new(0, 2, 1)),
97 ]
98 );
99
100 assert_eq!(
101 changelog.versions().cloned().collect::<Vec<_>>(),
102 vec![
103 semver::Version::new(0, 1, 0),
104 semver::Version::new(0, 1, 1),
105 semver::Version::new(0, 1, 2),
106 semver::Version::new(0, 2, 0),
107 semver::Version::new(0, 2, 1),
108 ]
109 );
110 }
111}