Improve error handling for which::which failures

Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
This commit is contained in:
Michael Davis 2024-01-23 13:36:53 -05:00 committed by Blaž Hrastnik
parent 6d724a8f33
commit cb25d13028
6 changed files with 33 additions and 9 deletions

View File

@ -113,7 +113,7 @@ pub fn stdio(
id: usize, id: usize,
) -> Result<(Self, UnboundedReceiver<Payload>)> { ) -> Result<(Self, UnboundedReceiver<Payload>)> {
// Resolve path to the binary // Resolve path to the binary
let cmd = helix_stdx::env::which(cmd).map_err(|err| anyhow::anyhow!(err))?; let cmd = helix_stdx::env::which(cmd)?;
let process = Command::new(cmd) let process = Command::new(cmd)
.args(args) .args(args)

View File

@ -19,6 +19,8 @@ pub enum Error {
#[error("server closed the stream")] #[error("server closed the stream")]
StreamClosed, StreamClosed,
#[error(transparent)] #[error(transparent)]
ExecutableNotFound(#[from] helix_stdx::env::ExecutableNotFoundError),
#[error(transparent)]
Other(#[from] anyhow::Error), Other(#[from] anyhow::Error),
} }
pub type Result<T> = core::result::Result<T, Error>; pub type Result<T> = core::result::Result<T, Error>;

View File

@ -86,10 +86,8 @@ pub fn get_language(name: &str) -> Result<Language> {
} }
fn ensure_git_is_available() -> Result<()> { fn ensure_git_is_available() -> Result<()> {
match helix_stdx::env::which("git") { helix_stdx::env::which("git")?;
Ok(_cmd) => Ok(()), Ok(())
Err(err) => Err(anyhow::anyhow!("'git' could not be found ({err})")),
}
} }
pub fn fetch_grammars() -> Result<()> { pub fn fetch_grammars() -> Result<()> {

View File

@ -183,7 +183,7 @@ pub fn start(
doc_path: Option<&std::path::PathBuf>, doc_path: Option<&std::path::PathBuf>,
) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> { ) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
// Resolve path to the binary // Resolve path to the binary
let cmd = helix_stdx::env::which(cmd).map_err(|err| anyhow::anyhow!(err))?; let cmd = helix_stdx::env::which(cmd)?;
let process = Command::new(cmd) let process = Command::new(cmd)
.envs(server_environment) .envs(server_environment)

View File

@ -44,6 +44,8 @@ pub enum Error {
#[error("Unhandled")] #[error("Unhandled")]
Unhandled, Unhandled,
#[error(transparent)] #[error(transparent)]
ExecutableNotFound(#[from] helix_stdx::env::ExecutableNotFoundError),
#[error(transparent)]
Other(#[from] anyhow::Error), Other(#[from] anyhow::Error),
} }

View File

@ -1,6 +1,5 @@
pub use which::which;
use std::{ use std::{
ffi::OsStr,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::RwLock, sync::RwLock,
}; };
@ -36,10 +35,33 @@ pub fn env_var_is_set(env_var_name: &str) -> bool {
std::env::var_os(env_var_name).is_some() std::env::var_os(env_var_name).is_some()
} }
pub fn binary_exists(binary_name: &str) -> bool { pub fn binary_exists<T: AsRef<OsStr>>(binary_name: T) -> bool {
which::which(binary_name).is_ok() which::which(binary_name).is_ok()
} }
pub fn which<T: AsRef<OsStr>>(
binary_name: T,
) -> Result<std::path::PathBuf, ExecutableNotFoundError> {
which::which(binary_name.as_ref()).map_err(|err| ExecutableNotFoundError {
command: binary_name.as_ref().to_string_lossy().into_owned(),
inner: err,
})
}
#[derive(Debug)]
pub struct ExecutableNotFoundError {
command: String,
inner: which::Error,
}
impl std::fmt::Display for ExecutableNotFoundError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "command '{}' not found: {}", self.command, self.inner)
}
}
impl std::error::Error for ExecutableNotFoundError {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{current_working_dir, set_current_working_dir}; use super::{current_working_dir, set_current_working_dir};