knope_versioning/semver/
rule.rs

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