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 /// `treeboot init` refused to replace an existing target.
183 #[error("init target already exists: {0:?}")]
184 InitTargetExists(PathBuf),
185
186 /// An init file could not be written.
187 #[error("failed to write init target {path:?}: {source}")]
188 InitIo {
189 /// Init target path.
190 path: PathBuf,
191 /// Source I/O error.
192 #[source]
193 source: std::io::Error,
194 },
195}
196
197impl Error {
198 /// Returns the CLI exit code associated with this error.
199 #[must_use]
200 pub const fn exit_code(&self) -> u8 {
201 1
202 }
203}