Skip to main content

mit_commit_message_lints/mit/lib/
non_clean_behaviour.rs

1//! Differing behaviours on rebase
2use std::{
3    fmt::{Display, Formatter},
4    str::FromStr,
5};
6
7use crate::mit::lib::errors::DeserializeRebaseBehaviourError;
8
9/// Differing behaviours on non-clean repository
10#[derive(clap::ValueEnum, Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Copy)]
11pub enum BehaviourOption {
12    /// Change the commit message to include the current author
13    AddTo,
14    /// Do not change the commit message
15    NoChange,
16}
17
18const ADD_TO_DISPLAY: &str = "add-to";
19const NO_CHANGE_DISPLAY: &str = "no-change";
20
21impl FromStr for BehaviourOption {
22    type Err = DeserializeRebaseBehaviourError;
23
24    fn from_str(s: &str) -> Result<Self, Self::Err> {
25        match s.to_ascii_lowercase().as_str() {
26            ADD_TO_DISPLAY => Ok(Self::AddTo),
27            NO_CHANGE_DISPLAY => Ok(Self::NoChange),
28            _ => Err(DeserializeRebaseBehaviourError { src: s.into() }),
29        }
30    }
31}
32
33impl Display for BehaviourOption {
34    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
35        match self {
36            Self::AddTo => write!(f, "{ADD_TO_DISPLAY}"),
37            Self::NoChange => write!(f, "{NO_CHANGE_DISPLAY}"),
38        }
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use std::str::FromStr;
45
46    use super::BehaviourOption;
47
48    #[test]
49    fn from_str_accepts_lowercase() {
50        assert_eq!(
51            BehaviourOption::from_str("add-to").unwrap(),
52            BehaviourOption::AddTo,
53            "Expected 'add-to' to parse as AddTo"
54        );
55        assert_eq!(
56            BehaviourOption::from_str("no-change").unwrap(),
57            BehaviourOption::NoChange,
58            "Expected 'no-change' to parse as NoChange"
59        );
60    }
61
62    #[test]
63    fn from_str_rejects_unknown() {
64        assert!(
65            BehaviourOption::from_str("unknown").is_err(),
66            "Expected parsing an unknown behaviour option to return an error"
67        );
68    }
69
70    #[test]
71    fn from_str_is_case_insensitive_like_value_enum() {
72        // clap::ValueEnum accepts any casing; FromStr should too
73        assert_eq!(
74            BehaviourOption::from_str("Add-To").unwrap(),
75            BehaviourOption::AddTo,
76            "Expected 'Add-To' to parse as AddTo (case insensitive)"
77        );
78        assert_eq!(
79            BehaviourOption::from_str("ADD-TO").unwrap(),
80            BehaviourOption::AddTo,
81            "Expected 'ADD-TO' to parse as AddTo (case insensitive)"
82        );
83        assert_eq!(
84            BehaviourOption::from_str("No-Change").unwrap(),
85            BehaviourOption::NoChange,
86            "Expected 'No-Change' to parse as NoChange (case insensitive)"
87        );
88        assert_eq!(
89            BehaviourOption::from_str("NO-CHANGE").unwrap(),
90            BehaviourOption::NoChange,
91            "Expected 'NO-CHANGE' to parse as NoChange (case insensitive)"
92        );
93    }
94
95    #[test]
96    fn display_round_trips_through_from_str() {
97        for original in [BehaviourOption::AddTo, BehaviourOption::NoChange] {
98            let displayed = original.to_string();
99            let parsed = BehaviourOption::from_str(&displayed);
100            assert_eq!(
101                parsed.unwrap(),
102                original,
103                "Expected display output to round-trip through from_str"
104            );
105        }
106    }
107}