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}