1use std::io;
2use std::path::PathBuf;
3use std::process::ExitStatus;
4use std::time::Duration;
5
6#[derive(Debug, thiserror::Error)]
8#[error("{action} {}: {source}", path.display())]
9pub struct FileError {
10 pub action: &'static str,
11 pub path: PathBuf,
12 #[source]
13 pub source: io::Error,
14}
15
16#[derive(Debug, thiserror::Error)]
18pub enum PruneError {
19 #[error(transparent)]
20 File(#[from] FileError),
21 #[error(transparent)]
23 Git(#[from] GitCallError),
24}
25
26#[derive(Debug, thiserror::Error)]
28pub enum ResetError {
29 #[error(transparent)]
31 Git(#[from] GitCallError),
32 #[error(transparent)]
33 Symlinks(#[from] FileError),
34}
35
36#[derive(Debug, PartialEq, Eq, thiserror::Error)]
38pub enum HttpsAccessError {
39 #[error("Invalid credentials: a line break or a nul byte")]
41 CredentialLineBreak,
42 #[error("expected an http or https url")]
43 NotHttp,
44 #[error("Invalid url: its host or port could not be parsed")]
46 Unparsable,
47 #[error("expected an https credential")]
48 NotHttpsCredential,
49}
50
51#[derive(Debug, thiserror::Error)]
53pub enum CloneError {
54 #[error(transparent)]
55 Access(#[from] HttpsAccessError),
56 #[error(transparent)]
57 Git(#[from] GitCallError),
58 #[error(transparent)]
60 Info(#[from] FileError),
61 #[error(transparent)]
62 SshKey(#[from] SshKeyError),
63 #[error(transparent)]
64 Sts(#[from] StsError),
65}
66
67#[derive(Debug, thiserror::Error)]
69pub enum SshKeyError {
70 #[error("the SSH key is not base64: {0}")]
71 Decode(#[from] base64::DecodeError),
72 #[error("the SSH key could not be written: {0}")]
73 File(#[source] io::Error),
74 #[error("the SSH key path cannot be quoted for the shell: {0}")]
75 Path(#[from] shlex::QuoteError),
76}
77
78#[derive(Debug, thiserror::Error)]
80pub enum LsRemoteError {
81 #[error(transparent)]
82 SshKey(#[from] SshKeyError),
83 #[error(transparent)]
84 Git(#[from] GitCallError),
85}
86
87#[derive(Debug, thiserror::Error)]
89pub enum SshHostError {
90 #[error("Invalid ssh url: expected user@host:path or ssh://user@host[:port]/path")]
92 Malformed,
93 #[error("Could not resolve the hostname {host}: {source}")]
94 Unresolved {
95 host: String,
96 #[source]
97 source: io::Error,
98 },
99 #[error("No IP addresses resolved for hostname: {host}")]
100 NoAddresses { host: String },
101 #[error("SSH host validation failed for {host}: {reason}")]
102 Local {
103 host: String,
104 reason: crate::local_address::LocalAddress,
105 },
106}
107
108#[derive(Debug, thiserror::Error)]
110pub enum StsError {
111 #[error("STS refused the role {arn}: {code}: {message}")]
113 Refused {
114 arn: String,
115 code: String,
116 message: String,
117 },
118 #[error("STS took too long to connect for the role {arn}: {reason}")]
119 ConnectTimeout { arn: String, reason: String },
120 #[error("STS took too long to answer the role {arn}: {reason}")]
122 ReadTimeout { arn: String, reason: String },
123 #[error("STS closed the connection for the role {arn}: {reason}")]
125 ConnectionClosed { arn: String, reason: String },
126 #[error("STS could not be connected to for the role {arn}: {reason}")]
128 NoConnection { arn: String, reason: String },
129 #[error("STS could not be asked for the role {arn}: {reason}")]
131 Unreachable { arn: String, reason: String },
132 #[error("STS answered the role {arn} without credentials")]
133 NoCredentials { arn: String },
134}
135
136#[derive(Debug, thiserror::Error)]
138pub enum CodecommitLsRemoteError {
139 #[error(transparent)]
140 Sts(#[from] StsError),
141 #[error(transparent)]
142 Git(#[from] GitCallError),
143}
144
145#[derive(Debug, thiserror::Error)]
147pub enum HttpsLsRemoteError {
148 #[error(transparent)]
149 Access(#[from] HttpsAccessError),
150 #[error(transparent)]
151 Git(#[from] GitCallError),
152}
153
154#[derive(Debug, thiserror::Error)]
155pub enum GitCallError {
156 #[error("git {command} could not start: {source}")]
157 NotStarted {
158 command: &'static str,
159 source: io::Error,
160 },
161 #[error("git {command} did not finish within {after:?}")]
162 TimedOut {
163 command: &'static str,
164 after: Duration,
165 },
166 #[error("git {command} exited with {status}: {stderr}")]
168 Refused {
169 command: &'static str,
170 status: ExitStatus,
171 stderr: String,
172 },
173 #[error("git {command} got an argument with an embedded null byte")]
175 NullByte { command: &'static str },
176 #[error("git {command} printed something unreadable: {reason}")]
177 Malformed {
178 command: &'static str,
179 reason: String,
180 },
181}
182
183#[derive(Debug, thiserror::Error)]
185pub enum DownloadError {
186 #[error("writing the archive: {0}")]
189 Write(#[source] io::Error),
190 #[error(transparent)]
191 Fetch(#[from] FetchError),
192 #[error(transparent)]
193 Extract(#[from] ExtractError),
194 #[error(transparent)]
196 Reset(#[from] GitCallError),
197 #[error("pruning the working tree: {0}")]
198 Prune(#[from] PruneError),
199 #[error("placing the repository: {0}")]
202 Place(#[source] io::Error),
203}
204
205#[derive(Debug, thiserror::Error)]
207pub enum FetchError {
208 #[error("invalid url {url}: {reason}")]
209 InvalidUrl { url: String, reason: String },
210 #[error("not an http url: {0}")]
211 NonHttpUrl(String),
212 #[error("could not connect: {0}")]
214 Connect(#[source] reqwest::Error),
215 #[error("connecting timed out: {0}")]
216 ConnectTimeout(#[source] reqwest::Error),
217 #[error("no response in time: {0}")]
219 Timeout(#[source] reqwest::Error),
220 #[error("the server disconnected: {0}")]
222 Disconnected(#[source] reqwest::Error),
223 #[error("the socket failed: {source}")]
226 Socket {
227 reset: bool,
228 errno: Option<i32>,
229 source: reqwest::Error,
230 },
231 #[error("malformed response: {0}")]
232 Malformed(#[source] reqwest::Error),
233 #[error("the server answered {0}")]
234 Status(reqwest::StatusCode),
235 #[error("the body was cut: {0}")]
237 BodyCut(#[source] reqwest::Error),
238 #[error("the body did not arrive in time: {0}")]
240 BodyTimeout(#[source] reqwest::Error),
241 #[error("the request failed: {0}")]
242 Other(#[source] reqwest::Error),
243}
244
245#[derive(Debug, thiserror::Error)]
247pub enum ExtractError {
248 #[error("corrupt archive: {0}")]
251 Corrupt(#[source] io::Error),
252 #[error("truncated archive: {0}")]
254 Truncated(#[source] io::Error),
255 #[error("the archive holds no repository: {0}")]
257 NoRepository(String),
258 #[error("extracting the archive: {0}")]
259 Io(#[source] io::Error),
260}