knope_versioning/changes/
mod.rs1use std::{fmt::Display, sync::Arc};
2
3pub use changeset::CHANGESET_DIR;
4use git_conventional::FooterToken;
5
6use crate::{
7 package,
8 release_notes::{CommitFooter, CustomChangeType, SectionSource},
9};
10
11mod changeset;
12pub mod conventional_commit;
13
14#[derive(Clone, Debug, Eq, PartialEq)]
16pub struct Change {
17 pub change_type: ChangeType,
18 pub description: Arc<str>,
19 pub original_source: ChangeSource,
20}
21
22impl Change {
23 pub fn from_changesets<'a>(
24 package_name: &'a package::Name,
25 releases: &'a [changesets::Release],
26 ) -> impl Iterator<Item = Self> + 'a {
27 releases
28 .iter()
29 .find(|release| *package_name == release.package_name)
30 .into_iter()
31 .flat_map(|release_changes| release_changes.changes.clone().into_iter().map(Self::from))
32 }
33}
34
35impl From<changesets::PackageChange> for Change {
36 fn from(package_change: changesets::PackageChange) -> Self {
37 Self {
38 change_type: package_change.change_type.into(),
39 description: package_change.summary,
40 original_source: ChangeSource::ChangeFile(package_change.unique_id),
41 }
42 }
43}
44
45#[derive(Clone, Debug, Hash, Eq, PartialEq)]
46pub enum ChangeType {
47 Breaking,
48 Feature,
49 Fix,
50 Custom(SectionSource),
51}
52
53impl ChangeType {
54 #[must_use]
55 pub fn to_changeset_type(&self) -> Option<changesets::ChangeType> {
56 match self {
57 Self::Breaking => Some(changesets::ChangeType::Major),
58 Self::Feature => Some(changesets::ChangeType::Minor),
59 Self::Fix => Some(changesets::ChangeType::Patch),
60 Self::Custom(SectionSource::CustomChangeType(custom)) => {
61 Some(changesets::ChangeType::Custom(custom.to_string()))
62 }
63 Self::Custom(SectionSource::CommitFooter(_)) => None,
64 }
65 }
66}
67
68impl From<ChangeType> for changesets::ChangeType {
69 fn from(value: ChangeType) -> Self {
70 match value {
71 ChangeType::Breaking => Self::Major,
72 ChangeType::Feature => Self::Minor,
73 ChangeType::Fix => Self::Patch,
74 ChangeType::Custom(custom) => Self::Custom(custom.to_string()),
75 }
76 }
77}
78
79impl From<&changesets::ChangeType> for ChangeType {
80 fn from(value: &changesets::ChangeType) -> Self {
81 match value {
82 changesets::ChangeType::Major => Self::Breaking,
83 changesets::ChangeType::Minor => Self::Feature,
84 changesets::ChangeType::Patch => Self::Fix,
85 changesets::ChangeType::Custom(custom) => {
86 Self::Custom(SectionSource::CustomChangeType(custom.clone().into()))
87 }
88 }
89 }
90}
91
92impl From<CustomChangeType> for ChangeType {
93 fn from(custom: CustomChangeType) -> Self {
94 changesets::ChangeType::from(String::from(custom)).into()
95 }
96}
97
98impl From<changesets::ChangeType> for ChangeType {
99 fn from(change_type: changesets::ChangeType) -> Self {
100 match change_type {
101 changesets::ChangeType::Major => Self::Breaking,
102 changesets::ChangeType::Minor => Self::Feature,
103 changesets::ChangeType::Patch => Self::Fix,
104 changesets::ChangeType::Custom(custom) => {
105 Self::Custom(SectionSource::CustomChangeType(custom.into()))
106 }
107 }
108 }
109}
110
111impl From<CommitFooter> for ChangeType {
112 fn from(footer: CommitFooter) -> Self {
113 Self::Custom(SectionSource::CommitFooter(footer))
114 }
115}
116
117impl From<FooterToken<'_>> for ChangeType {
118 fn from(footer: FooterToken) -> Self {
119 if footer.breaking() {
120 Self::Breaking
121 } else {
122 Self::Custom(SectionSource::CommitFooter(CommitFooter::from(footer)))
123 }
124 }
125}
126
127#[derive(Clone, Debug, Eq, PartialEq)]
128pub enum ChangeSource {
129 ConventionalCommit(String),
130 ChangeFile(Arc<changesets::UniqueId>),
131}
132
133impl Display for ChangeSource {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 match self {
136 Self::ConventionalCommit(commit) => write!(f, "commit {commit}"),
137 Self::ChangeFile(id) => write!(f, "changeset {}", id.to_file_name()),
138 }
139 }
140}