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