1use std::io;
2use std::path::PathBuf;
3
4use crate::pm::PmError;
5use crate::report::Report;
6
7#[derive(Debug)]
8pub enum AppError {
9 HomeDirUnavailable,
10 ReadConfig {
11 path: PathBuf,
12 source: io::Error,
13 },
14 ParseConfigToml(toml::de::Error),
15 MissingConfigField(&'static str),
16 CreateDir {
17 path: PathBuf,
18 source: io::Error,
19 },
20 InstallToolchain {
21 user: String,
22 repo: String,
23 source: String,
24 },
25 MoveToolchain {
26 from: PathBuf,
27 to: PathBuf,
28 source: io::Error,
29 },
30 RemoveToolchain {
31 path: PathBuf,
32 source: io::Error,
33 },
34 ReadScript {
35 path: PathBuf,
36 source: io::Error,
37 },
38 PackageManager(PmError),
39 UnsupportedToolchain {
40 toolchain: String,
41 detail: &'static str,
42 },
43}
44
45impl AppError {
46 pub fn report(&self) -> Report {
47 match self {
48 Self::HomeDirUnavailable => Report::new("could not resolve home directory")
49 .detail("`$HOME` is unavailable in the current environment"),
50 Self::ReadConfig { path, source } => Report::new("failed to read config")
51 .detail(format!("path: {}", path.display()))
52 .detail(format!("cause: {source}")),
53 Self::ParseConfigToml(source) => Report::new("failed to parse config")
54 .detail("expected a valid TOML document")
55 .detail(format!("cause: {source}")),
56 Self::MissingConfigField(field) => {
57 Report::new("config is missing a required field").detail(format!("field: {field}"))
58 }
59 Self::CreateDir { path, source } => Report::new("failed to prepare directory")
60 .detail(format!("path: {}", path.display()))
61 .detail(format!("cause: {source}")),
62 Self::InstallToolchain { user, repo, source } => {
63 Report::new(format!("failed to install toolchain `{repo}`"))
64 .detail(format!("source: {user}/{repo}"))
65 .detail(format!("cause: {source}"))
66 }
67 Self::MoveToolchain { from, to, source } => {
68 Report::new("failed to place installed toolchain")
69 .detail(format!("from: {}", from.display()))
70 .detail(format!("to: {}", to.display()))
71 .detail(format!("cause: {source}"))
72 }
73 Self::RemoveToolchain { path, source } => Report::new("failed to remove toolchain")
74 .detail(format!("path: {}", path.display()))
75 .detail(format!("cause: {source}")),
76 Self::ReadScript { path, source } => Report::new("failed to read script")
77 .detail(format!("path: {}", path.display()))
78 .detail(format!("cause: {source}")),
79 Self::PackageManager(error) => error.report(),
80 Self::UnsupportedToolchain { toolchain, detail } => Report::new(format!(
81 "toolchain `{toolchain}` is not supported on this platform"
82 ))
83 .detail(*detail),
84 }
85 }
86}