use thiserror::Error;
#[derive(Debug, Error)]
pub enum CargoFreshError {
#[error("`cargo install --list` failed: {source}")]
CargoListFailed {
#[source]
source: anyhow::Error,
},
}
pub fn hint_for(err: &anyhow::Error) -> Option<&'static str> {
for cause in err.chain() {
if let Some(cf) = cause.downcast_ref::<CargoFreshError>() {
return Some(match cf {
CargoFreshError::CargoListFailed { .. } => {
"Is `cargo` on your PATH? Try `cargo --version` to verify the toolchain."
}
});
}
if let Some(re) = cause.downcast_ref::<reqwest::Error>() {
if re.is_connect() || re.is_timeout() {
return Some(
"Network connect/timeout. Check connectivity to index.crates.io, \
or set HTTPS_PROXY if behind a proxy.",
);
}
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hint_for_cargo_list_failed() {
let err: anyhow::Error = CargoFreshError::CargoListFailed {
source: anyhow::anyhow!("exit code 101"),
}
.into();
assert!(hint_for(&err).unwrap().contains("cargo --version"));
}
#[test]
fn hint_for_wrapped_cargo_fresh_error() {
let err = anyhow::Error::from(CargoFreshError::CargoListFailed {
source: anyhow::anyhow!("exit code 101"),
})
.context("while listing installed packages");
assert!(hint_for(&err).unwrap().contains("cargo --version"));
}
#[test]
fn hint_for_unrelated_error_returns_none() {
let err = anyhow::anyhow!("something else entirely");
assert!(hint_for(&err).is_none());
}
}