1use thiserror::Error;
4
5#[derive(Error, Debug)]
7pub enum ScriptError {
8 #[error("Command not found: {0}")]
10 CommandNotFound(String),
11
12 #[error("Permission denied: {0}")]
14 PermissionDenied(String),
15
16 #[error("Invalid argument: {0}")]
18 InvalidArgument(String),
19
20 #[error("Invalid working directory: {0}")]
22 InvalidWorkingDirectory(String),
23
24 #[error("Command failed with exit code {code}: {stderr}")]
26 ExecutionFailed {
27 code: i32,
29 stderr: String,
31 },
32
33 #[error("Command timed out after {0:?}")]
35 Timeout(std::time::Duration),
36
37 #[error("IO error: {0}")]
39 IoError(#[from] std::io::Error),
40
41 #[error("Environment error: {0}")]
43 EnvironmentError(String),
44
45 #[error("Encoding error: {0}")]
47 EncodingError(String),
48
49 #[error("Validation error: {0}")]
51 ValidationError(String),
52
53 #[error("Pipeline error: {0}")]
55 PipelineError(String),
56
57 #[error("Pipeline has no commands")]
59 PipelineEmpty,
60
61 #[error("Failed to connect pipeline stdin: {0}")]
63 PipelineStdinError(String),
64
65 #[error("Failed to connect pipeline stdout: {0}")]
67 PipelineStdoutError(String),
68
69 #[error("Argument validation error: {0}")]
71 ArgumentError(String),
72
73 #[error("Child process error: {0}")]
75 ChildError(String),
76
77 #[error("Shell execution error: {0}")]
79 ShellError(String),
80
81 #[error("Error: {0}")]
83 Other(String),
84}
85
86pub type ScriptResult<T> = Result<T, ScriptError>;
88
89impl From<std::process::Output> for ScriptError {
90 fn from(output: std::process::Output) -> Self {
91 let code = output.status.code().unwrap_or(-1);
92 let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
93 ScriptError::ExecutionFailed { code, stderr }
94 }
95}