1use siderite_core::ServerError;
7use siderite_migrations::MigrationError;
8use thiserror::Error;
9
10#[derive(Debug, Error)]
12#[non_exhaustive]
13pub enum CliError {
14 #[error("{0}")]
16 Usage(String),
17 #[error(
19 "no database configured for alias `{alias}` (set it in the settings, or pass --database-url)"
20 )]
21 NoDatabase {
22 alias: String,
24 },
25 #[error("cannot connect to database `{alias}`: {source}")]
27 Connect {
28 alias: String,
30 #[source]
32 source: MigrationError,
33 },
34 #[error(transparent)]
36 Migration(#[from] MigrationError),
37 #[error(transparent)]
39 Server(#[from] ServerError),
40 #[error("cannot generate the OpenAPI document: {0}")]
42 OpenApi(String),
43 #[error("cannot run `{program}`: {reason}")]
45 Shell {
46 program: &'static str,
48 reason: String,
50 },
51 #[error("{0}")]
53 Io(String),
54 #[error("{0}")]
56 Conflict(String),
57 #[error("timed out after {after:?} {what}")]
59 Timeout {
60 what: String,
62 after: std::time::Duration,
64 },
65}
66
67impl CliError {
68 pub fn usage(message: impl Into<String>) -> Self {
70 Self::Usage(message.into())
71 }
72
73 pub fn exit_code(&self) -> u8 {
75 match self {
76 Self::Usage(_) | Self::Migration(MigrationError::Usage(_)) => 2,
77 _ => 1,
78 }
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn usage_errors_exit_with_two() {
88 assert_eq!(CliError::usage("bad").exit_code(), 2);
89 assert_eq!(CliError::from(MigrationError::usage("bad")).exit_code(), 2);
90 assert_eq!(
91 CliError::NoDatabase {
92 alias: "default".into()
93 }
94 .exit_code(),
95 1
96 );
97 }
98}