use std::{fmt, io};
use camino::{Utf8Path, Utf8PathBuf};
use walkdir;
use super::options::CwdMode;
#[derive(Debug)]
pub(crate) enum ResolveError {
NotFound {
command: String,
dirs: Vec<Utf8PathBuf>,
cwd_mode: CwdMode,
},
DirectNotFound {
command: String,
path: Utf8PathBuf,
},
Args {
detail: String,
},
Canonicalize {
path: Utf8PathBuf,
source: io::Error,
},
IsExecutable {
path: Utf8PathBuf,
source: io::Error,
},
CanonicalizeNonUtf8,
WorkspaceNonUtf8 {
command: String,
path: String,
},
WalkDir {
source: walkdir::Error,
},
CwdResolve {
source: io::Error,
},
CwdNonUtf8,
}
impl ResolveError {
pub(super) fn args(detail: impl fmt::Display) -> Self {
Self::Args {
detail: detail.to_string(),
}
}
pub(super) const fn category(&self) -> &'static str {
match self {
Self::NotFound { .. } => "not_found",
Self::DirectNotFound { .. } => "direct_not_found",
Self::Args { .. } => "args",
Self::Canonicalize { .. } => "canonicalize",
Self::IsExecutable { .. } => "is_executable",
Self::CanonicalizeNonUtf8 => "canonicalize_non_utf8",
Self::WorkspaceNonUtf8 { .. } => "workspace_non_utf8",
Self::WalkDir { .. } => "walkdir",
Self::CwdResolve { .. } => "cwd_resolve",
Self::CwdNonUtf8 => "cwd_non_utf8",
}
}
}
impl fmt::Display for ResolveError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::IsExecutable { path, source } => {
write!(
formatter,
"failed to inspect executable path '{path}': {source}"
)
}
_ => formatter.write_str(self.category()),
}
}
}
impl std::error::Error for ResolveError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Canonicalize { source, .. }
| Self::IsExecutable { source, .. }
| Self::CwdResolve { source } => Some(source),
Self::WalkDir { source } => Some(source),
Self::NotFound { .. }
| Self::DirectNotFound { .. }
| Self::Args { .. }
| Self::CanonicalizeNonUtf8
| Self::WorkspaceNonUtf8 { .. }
| Self::CwdNonUtf8 => None,
}
}
}
pub(super) fn not_found(command: &str, dirs: &[&Utf8Path], mode: CwdMode) -> ResolveError {
ResolveError::NotFound {
command: command.to_owned(),
dirs: dirs.iter().map(|dir| dir.to_path_buf()).collect(),
cwd_mode: mode,
}
}
pub(super) fn direct_not_found_error(command: &str, path: &camino::Utf8Path) -> ResolveError {
ResolveError::DirectNotFound {
command: command.to_owned(),
path: path.to_path_buf(),
}
}