1use std::{error::Error, fmt};
2
3use super::model::{ICP_CLI_SUPPORTED_VERSION_RANGE, REQUIRED_ICP_CLI_VERSION};
4
5#[derive(Debug)]
10pub enum IcpCommandError {
11 Io(std::io::Error),
12 MissingCli {
13 executable: String,
14 },
15 IncompatibleCliVersion {
16 executable: String,
17 found: String,
18 },
19 Failed {
20 command: String,
21 stderr: String,
22 },
23 Json {
24 command: String,
25 output: String,
26 source: serde_json::Error,
27 },
28 SnapshotIdUnavailable {
29 output: String,
30 },
31}
32
33impl fmt::Display for IcpCommandError {
34 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
36 match self {
37 Self::Io(err) => write!(formatter, "{err}"),
38 Self::MissingCli { executable } => {
39 write!(
40 formatter,
41 "icp-cli executable not found: {executable}\nrequired: icp-cli {ICP_CLI_SUPPORTED_VERSION_RANGE}\nnext: install icp-cli {REQUIRED_ICP_CLI_VERSION} from https://github.com/dfinity/icp-cli/releases/tag/v{REQUIRED_ICP_CLI_VERSION}, or pass top-level --icp <path>"
42 )
43 }
44 Self::IncompatibleCliVersion { executable, found } => {
45 write!(
46 formatter,
47 "unsupported icp-cli version for {executable}\nfound: {found}\nrequired: icp-cli {ICP_CLI_SUPPORTED_VERSION_RANGE}\nnext: install icp-cli {REQUIRED_ICP_CLI_VERSION} from https://github.com/dfinity/icp-cli/releases/tag/v{REQUIRED_ICP_CLI_VERSION}, or pass top-level --icp <path>"
48 )
49 }
50 Self::Failed { command, stderr } => {
51 write!(formatter, "icp command failed: {command}\n{stderr}")
52 }
53 Self::Json {
54 command,
55 output,
56 source,
57 } => {
58 write!(
59 formatter,
60 "could not parse icp json output for {command}: {source}\n{output}"
61 )
62 }
63 Self::SnapshotIdUnavailable { output } => {
64 write!(
65 formatter,
66 "could not parse snapshot id from icp output: {output}"
67 )
68 }
69 }
70 }
71}
72
73impl Error for IcpCommandError {
74 fn source(&self) -> Option<&(dyn Error + 'static)> {
76 match self {
77 Self::Io(err) => Some(err),
78 Self::Json { source, .. } => Some(source),
79 Self::Failed { .. }
80 | Self::IncompatibleCliVersion { .. }
81 | Self::MissingCli { .. }
82 | Self::SnapshotIdUnavailable { .. } => None,
83 }
84 }
85}
86
87impl From<std::io::Error> for IcpCommandError {
88 fn from(err: std::io::Error) -> Self {
90 Self::Io(err)
91 }
92}