Skip to main content

treeboot_core/
error.rs

1use std::path::PathBuf;
2use std::process::ExitStatus;
3
4/// Error type for `treeboot-core` operations.
5#[derive(Debug, thiserror::Error)]
6pub enum Error {
7    /// The current working directory could not be read.
8    #[error("failed to read current directory: {source}")]
9    CurrentDir {
10        /// Source I/O error.
11        #[source]
12        source: std::io::Error,
13    },
14
15    /// A filesystem path could not be normalized.
16    #[error("failed to normalize path {path:?}: {source}")]
17    NormalizePath {
18        /// Path that failed normalization.
19        path: PathBuf,
20        /// Source I/O error.
21        #[source]
22        source: std::io::Error,
23    },
24
25    /// The command was not run from a Git worktree.
26    #[error("not inside a Git worktree")]
27    NotGitWorktree,
28
29    /// A Git command could not be spawned.
30    #[error("failed to run {command}: {source}")]
31    GitIo {
32        /// Human-readable command label.
33        command: String,
34        /// Source I/O error.
35        #[source]
36        source: std::io::Error,
37    },
38
39    /// A Git command exited unsuccessfully.
40    #[error("{command} failed: {stderr}")]
41    GitFailed {
42        /// Human-readable command label.
43        command: String,
44        /// Standard error from Git.
45        stderr: String,
46    },
47
48    /// No root checkout path could be determined.
49    #[error("could not determine root checkout path")]
50    RootPathNotFound,
51
52    /// A specifically requested config file does not exist.
53    #[error("config file not found: {0:?}")]
54    ConfigNotFound(PathBuf),
55
56    /// A config file could not be read.
57    #[error("failed to read config {path:?}: {source}")]
58    ConfigIo {
59        /// Config file path.
60        path: PathBuf,
61        /// Source I/O error.
62        #[source]
63        source: std::io::Error,
64    },
65
66    /// A config file contains invalid TOML.
67    #[error("invalid config {path:?}: {message}")]
68    ConfigParse {
69        /// Config file path.
70        path: PathBuf,
71        /// Parse error message.
72        message: String,
73    },
74
75    /// A config file contains unsupported or invalid declarations.
76    #[error("invalid config {path:?}: {message}")]
77    ConfigInvalid {
78        /// Config file path.
79        path: PathBuf,
80        /// Validation error message.
81        message: String,
82    },
83
84    /// A treeboot boolean environment variable has an unsupported value.
85    #[error(
86        "invalid boolean environment value for {name}: {value:?} \
87         (expected one of 1, true, yes, on, 0, false, no, off)"
88    )]
89    InvalidBooleanEnv {
90        /// Environment variable name.
91        name: &'static str,
92        /// Environment variable value.
93        value: String,
94    },
95
96    /// No config was found while strict mode was enabled.
97    #[error("no config detected")]
98    NoConfigDetectedStrict,
99
100    /// The command was run from the root checkout while strict mode was enabled.
101    #[error("This is not a work tree")]
102    RootWorktreeStrict,
103
104    /// A configured command could not be spawned.
105    #[error("failed to run command {label}: {source}")]
106    CommandIo {
107        /// Human-readable command label.
108        label: String,
109        /// Source I/O error.
110        #[source]
111        source: std::io::Error,
112    },
113
114    /// A configured command exited unsuccessfully.
115    #[error("command {label} failed with {status}")]
116    CommandFailed {
117        /// Human-readable command label.
118        label: String,
119        /// Process exit status.
120        status: ExitStatus,
121    },
122
123    /// A file operation encountered an unsupported conflict.
124    #[error("{operation} file operation cannot use {path:?}: {message}")]
125    FileOperationConflict {
126        /// Operation being applied.
127        operation: &'static str,
128        /// Path involved in the conflict.
129        path: PathBuf,
130        /// Human-readable conflict detail.
131        message: String,
132    },
133
134    /// A manual file operation request is invalid.
135    #[error("invalid {operation} file operation: {message}")]
136    FileOperationInvalid {
137        /// Operation being planned.
138        operation: &'static str,
139        /// Human-readable validation detail.
140        message: String,
141    },
142
143    /// A file operation failed while accessing the filesystem.
144    #[error("{operation} file operation failed at {path:?}: {source}")]
145    FileOperationIo {
146        /// Operation being applied.
147        operation: &'static str,
148        /// Path being accessed.
149        path: PathBuf,
150        /// Source I/O error.
151        #[source]
152        source: std::io::Error,
153    },
154
155    /// An init script could not be spawned.
156    #[error("failed to run init script {path:?}: {source}")]
157    ScriptIo {
158        /// Script path.
159        path: PathBuf,
160        /// Source I/O error.
161        #[source]
162        source: std::io::Error,
163    },
164
165    /// An init script exited unsuccessfully.
166    #[error("init script {path:?} failed with {status}")]
167    ScriptFailed {
168        /// Script path.
169        path: PathBuf,
170        /// Script process status.
171        status: ExitStatus,
172    },
173
174    /// Writing output failed.
175    #[error("failed to write output: {source}")]
176    Output {
177        /// Source I/O error.
178        #[source]
179        source: std::io::Error,
180    },
181
182    /// Doctor diagnostics found fatal issues.
183    #[error("doctor found fatal issues")]
184    DoctorFailed,
185
186    /// `treeboot init` refused to replace an existing target.
187    #[error("init target already exists: {0:?}")]
188    InitTargetExists(PathBuf),
189
190    /// An init file could not be written.
191    #[error("failed to write init target {path:?}: {source}")]
192    InitIo {
193        /// Init target path.
194        path: PathBuf,
195        /// Source I/O error.
196        #[source]
197        source: std::io::Error,
198    },
199}
200
201impl Error {
202    /// Returns the CLI exit code associated with this error.
203    #[must_use]
204    pub const fn exit_code(&self) -> u8 {
205        1
206    }
207}