version_manager/
lib.rs

1pub mod cli;
2pub mod files;
3pub mod run;
4pub mod version;
5
6use clap::{Command, error};
7use thiserror::Error;
8
9#[derive(Error, Debug)]
10pub enum VersionError {
11    #[error("IO Error: {0}")]
12    IoError(#[from] std::io::Error),
13    #[error("TOML Deserialize Error: {0}")]
14    TomlDeError(#[from] toml::de::Error),
15    #[error("TOML Serialize Error: {0}")]
16    TomlSerError(#[from] toml::ser::Error),
17    #[error("Regex Error: {0}")]
18    RegexError(#[from] regex::Error),
19    #[error("Incomplete Command")]
20    IncompleteCommand,
21    #[error("Invalid Operation")]
22    InvalidOperation,
23    #[error("No Command specified")]
24    NoCommand,
25    #[error("No Value specified")]
26    NoValue,
27    #[error("No Negatives allowed")]
28    NoNegatives,
29    #[error("Invalid Command")]
30    InvalidCommand,
31    #[error("Empty Version")]
32    EmptyVersion,
33    #[error("Invalid Prerelease: {0}")]
34    InvalidPrerelease(String),
35    #[error("Invalid Version: {0}")]
36    InvalidVersion(#[from] semver::Error),
37    #[error("Package name required")]
38    PackageNameRequired,
39}
40
41pub type VersionResult<T> = Result<T, VersionError>;
42
43impl VersionError {
44    pub fn cmd_error(&self, cmd: &mut Command) -> error::Error {
45        cmd.error(Into::<error::ErrorKind>::into(self), self.to_string())
46    }
47
48    pub fn terminate(&self, cmd: &mut Command) -> ! {
49        let err = self.cmd_error(cmd);
50        err.exit()
51    }
52}
53
54impl From<&VersionError> for error::ErrorKind {
55    fn from(err: &VersionError) -> error::ErrorKind {
56        match err {
57            VersionError::IoError(_) => error::ErrorKind::Io,
58            VersionError::TomlDeError(_) => error::ErrorKind::Io,
59            VersionError::TomlSerError(_) => error::ErrorKind::Io,
60            VersionError::RegexError(_) => error::ErrorKind::ValueValidation,
61            VersionError::IncompleteCommand => {
62                error::ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
63            }
64            VersionError::InvalidOperation => {
65                error::ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
66            }
67            VersionError::NoCommand => error::ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand,
68            VersionError::NoValue => error::ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand,
69            VersionError::NoNegatives => error::ErrorKind::InvalidValue,
70            VersionError::InvalidCommand => error::ErrorKind::InvalidValue,
71            VersionError::EmptyVersion => error::ErrorKind::InvalidValue,
72            VersionError::InvalidPrerelease(_) => error::ErrorKind::InvalidValue,
73            VersionError::InvalidVersion(_) => error::ErrorKind::InvalidValue,
74            VersionError::PackageNameRequired => {
75                error::ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
76            }
77        }
78    }
79}
80
81#[cfg(test)]
82mod test {
83
84    use super::*;
85    use clap::CommandFactory;
86    use clap::error::ErrorKind;
87    #[test]
88    fn no_cmd() {
89        let error = VersionError::NoCommand;
90        let displ = error.to_string();
91        assert!(displ.len() > 0);
92        let cmd = cli::Cli::command();
93        let err = error.cmd_error(&mut cmd.clone());
94        let render = format!("{}", err.render());
95        assert!(render.len() > 0);
96        assert_eq!(
97            Into::<ErrorKind>::into(&error),
98            ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
99        );
100    }
101    #[test]
102    fn io_error() {
103        let error =
104            VersionError::IoError(std::io::Error::new(std::io::ErrorKind::NotFound, "test"));
105        let displ = error.to_string();
106        assert!(displ.len() > 0);
107        let cmd = cli::Cli::command();
108        let err = error.cmd_error(&mut cmd.clone());
109        let render = format!("{}", err.render());
110        assert!(render.len() > 0);
111        assert_eq!(Into::<ErrorKind>::into(&error), ErrorKind::Io);
112    }
113    #[test]
114    fn regex_error() {
115        let error = VersionError::RegexError(regex::Error::Syntax("test".to_string()));
116        let displ = error.to_string();
117        assert!(displ.len() > 0);
118        let cmd = cli::Cli::command();
119        let err = error.cmd_error(&mut cmd.clone());
120        let render = format!("{}", err.render());
121        assert!(render.len() > 0);
122        assert_eq!(Into::<ErrorKind>::into(&error), ErrorKind::ValueValidation);
123    }
124    #[test]
125    fn toml_de_error() {
126        use serde::de::Error;
127        let error = VersionError::TomlDeError(toml::de::Error::missing_field("test"));
128        let displ = error.to_string();
129        assert!(displ.len() > 0);
130        let cmd = cli::Cli::command();
131        let err = error.cmd_error(&mut cmd.clone());
132        let render = format!("{}", err.render());
133        assert!(render.len() > 0);
134        assert_eq!(Into::<ErrorKind>::into(&error), ErrorKind::Io);
135    }
136    #[test]
137    fn toml_ser_error() {
138        use serde::ser::Error;
139        let error = VersionError::TomlSerError(toml::ser::Error::custom("test"));
140        let displ = error.to_string();
141        assert!(displ.len() > 0);
142        let cmd = cli::Cli::command();
143        let err = error.cmd_error(&mut cmd.clone());
144        let render = format!("{}", err.render());
145        assert!(render.len() > 0);
146        assert_eq!(Into::<ErrorKind>::into(&error), ErrorKind::Io);
147    }
148    #[test]
149    fn incomplete_command_error() {
150        let error = VersionError::IncompleteCommand;
151        let displ = error.to_string();
152        assert!(displ.len() > 0);
153        let cmd = cli::Cli::command();
154        let err = error.cmd_error(&mut cmd.clone());
155        let render = format!("{}", err.render());
156        assert!(render.len() > 0);
157        assert_eq!(
158            Into::<ErrorKind>::into(&error),
159            ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
160        );
161    }
162    #[test]
163    fn invalid_operation_error() {
164        let error = VersionError::InvalidOperation;
165        let displ = error.to_string();
166        assert!(displ.len() > 0);
167        let cmd = cli::Cli::command();
168        let err = error.cmd_error(&mut cmd.clone());
169        let render = format!("{}", err.render());
170        assert!(render.len() > 0);
171        assert_eq!(
172            Into::<ErrorKind>::into(&error),
173            ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
174        );
175    }
176    #[test]
177    fn no_value_error() {
178        let error = VersionError::NoValue;
179        let displ = error.to_string();
180        assert!(displ.len() > 0);
181        let cmd = cli::Cli::command();
182        let err = error.cmd_error(&mut cmd.clone());
183        let render = format!("{}", err.render());
184        assert!(render.len() > 0);
185        assert_eq!(
186            Into::<ErrorKind>::into(&error),
187            ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
188        );
189    }
190    #[test]
191    fn no_negatives_error() {
192        let error = VersionError::NoNegatives;
193        let displ = error.to_string();
194        assert!(displ.len() > 0);
195        let cmd = cli::Cli::command();
196        let err = error.cmd_error(&mut cmd.clone());
197        let render = format!("{}", err.render());
198        assert!(render.len() > 0);
199        assert_eq!(Into::<ErrorKind>::into(&error), ErrorKind::InvalidValue);
200    }
201}