knope_versioning/semver/
rule.rs

1use std::fmt::Display;
2
3use serde::{Deserialize, Serialize};
4use tracing::debug;
5
6use super::Label;
7use crate::changes::{Change, ChangeType};
8
9/// The various rules that can be used when bumping semantic versions.
10#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
11#[serde(tag = "rule")]
12pub enum Rule {
13    Major,
14    Minor,
15    Patch,
16    Pre {
17        label: Label,
18        #[serde(skip)]
19        stable_rule: Stable,
20    },
21    Release,
22}
23
24impl From<Stable> for Rule {
25    fn from(conventional_rule: Stable) -> Self {
26        match conventional_rule {
27            Stable::Major => Rule::Major,
28            Stable::Minor => Rule::Minor,
29            Stable::Patch => Rule::Patch,
30        }
31    }
32}
33
34/// The rules that only apply to stable versions (no pre-releases)
35#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
36pub enum Stable {
37    Major,
38    Minor,
39    #[default]
40    Patch,
41}
42
43impl<'a, T: IntoIterator<Item = &'a Change>> From<T> for Stable {
44    fn from(changes: T) -> Self {
45        changes
46            .into_iter()
47            .map(|change| {
48                let rule = Self::from(&change.change_type);
49                debug!(
50                    "{change_source}\n\timplies rule {rule}",
51                    change_source = change.original_source
52                );
53                rule
54            })
55            .max()
56            .unwrap_or_default()
57    }
58}
59
60impl Display for Stable {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        match self {
63            Stable::Major => write!(f, "MAJOR"),
64            Stable::Minor => write!(f, "MINOR"),
65            Stable::Patch => write!(f, "PATCH"),
66        }
67    }
68}
69
70impl Ord for Stable {
71    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
72        match (self, other) {
73            (Self::Major, Self::Major)
74            | (Self::Minor, Self::Minor)
75            | (Self::Patch, Self::Patch) => std::cmp::Ordering::Equal,
76            (Self::Major, _) | (_, Self::Patch) => std::cmp::Ordering::Greater,
77            (_, Self::Major) | (Self::Patch, _) => std::cmp::Ordering::Less,
78        }
79    }
80}
81
82impl PartialOrd for Stable {
83    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
84        Some(self.cmp(other))
85    }
86}
87
88impl From<&ChangeType> for Stable {
89    fn from(value: &ChangeType) -> Self {
90        match value {
91            ChangeType::Feature => Self::Minor,
92            ChangeType::Breaking => Self::Major,
93            ChangeType::Custom(_) | ChangeType::Fix => Self::Patch,
94        }
95    }
96}