Skip to main content

mit_commit_message_lints/mit/lib/
rotation_option.rs

1//! Rotation strategy for the primary author across commits
2use std::{
3    fmt::{Display, Formatter},
4    str::FromStr,
5};
6
7use crate::mit::lib::errors::DeserializeRotationOptionError;
8
9/// How to rotate the primary author when pairing or mobbing
10#[derive(clap::ValueEnum, Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Copy)]
11pub enum RotationOption {
12    /// Rotation is disabled
13    Off,
14    /// Rotate through authors in order, one per commit
15    RoundRobin,
16    /// Shuffle authors randomly on each commit
17    Random,
18}
19
20const OFF_DISPLAY: &str = "off";
21const ROUND_ROBIN_DISPLAY: &str = "round-robin";
22const RANDOM_DISPLAY: &str = "random";
23
24impl FromStr for RotationOption {
25    type Err = DeserializeRotationOptionError;
26
27    fn from_str(s: &str) -> Result<Self, Self::Err> {
28        match s.to_ascii_lowercase().as_str() {
29            OFF_DISPLAY => Ok(Self::Off),
30            ROUND_ROBIN_DISPLAY => Ok(Self::RoundRobin),
31            RANDOM_DISPLAY => Ok(Self::Random),
32            _ => Err(DeserializeRotationOptionError { src: s.into() }),
33        }
34    }
35}
36
37impl Display for RotationOption {
38    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
39        match self {
40            Self::Off => write!(f, "{OFF_DISPLAY}"),
41            Self::RoundRobin => write!(f, "{ROUND_ROBIN_DISPLAY}"),
42            Self::Random => write!(f, "{RANDOM_DISPLAY}"),
43        }
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use std::str::FromStr;
50
51    use super::RotationOption;
52
53    #[test]
54    fn from_str_accepts_lowercase() {
55        assert_eq!(
56            RotationOption::from_str("round-robin").unwrap(),
57            RotationOption::RoundRobin,
58            "Expected 'round-robin' to parse as RoundRobin"
59        );
60    }
61
62    #[test]
63    fn from_str_rejects_unknown() {
64        assert!(
65            RotationOption::from_str("unknown").is_err(),
66            "Expected parsing an unknown rotation option to return an error"
67        );
68    }
69
70    #[test]
71    fn from_str_is_case_insensitive_like_value_enum() {
72        assert_eq!(
73            RotationOption::from_str("Round-Robin").unwrap(),
74            RotationOption::RoundRobin,
75            "Expected 'Round-Robin' to parse as RoundRobin (case insensitive)"
76        );
77        assert_eq!(
78            RotationOption::from_str("ROUND-ROBIN").unwrap(),
79            RotationOption::RoundRobin,
80            "Expected 'ROUND-ROBIN' to parse as RoundRobin (case insensitive)"
81        );
82    }
83
84    #[test]
85    fn from_str_accepts_random() {
86        assert_eq!(
87            RotationOption::from_str("random").unwrap(),
88            RotationOption::Random,
89            "Expected 'random' to parse as Random"
90        );
91    }
92
93    #[test]
94    fn from_str_accepts_random_case_insensitive() {
95        assert_eq!(
96            RotationOption::from_str("Random").unwrap(),
97            RotationOption::Random,
98            "Expected 'Random' to parse as Random (case insensitive)"
99        );
100        assert_eq!(
101            RotationOption::from_str("RANDOM").unwrap(),
102            RotationOption::Random,
103            "Expected 'RANDOM' to parse as Random (case insensitive)"
104        );
105    }
106
107    #[test]
108    fn display_round_trips_through_from_str() {
109        for original in [
110            RotationOption::Off,
111            RotationOption::RoundRobin,
112            RotationOption::Random,
113        ] {
114            let displayed = original.to_string();
115            let parsed = RotationOption::from_str(&displayed);
116            assert_eq!(
117                parsed.unwrap(),
118                original,
119                "Expected display output to round-trip through from_str"
120            );
121        }
122    }
123
124    #[test]
125    fn display_random_round_trips() {
126        let original = RotationOption::Random;
127        let displayed = original.to_string();
128        let parsed = RotationOption::from_str(&displayed);
129        assert_eq!(
130            parsed.unwrap(),
131            original,
132            "Expected Random display output to round-trip through from_str"
133        );
134    }
135}