Skip to content

Commit 34c0d46

Browse files
authored
Add CommandNotFound error type for better exec command failure diagnostic (#448)
1 parent b48fa6a commit 34c0d46

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

crates/runtime/runtime/src/impls/runtime/error.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use std::process::ExitStatus;
66
use cgp::core::error::{ErrorRaiser, ProvideErrorType};
77
use hermes_async_runtime_components::channel::types::ChannelClosedError;
88
use hermes_tokio_runtime_components::impls::os::child_process::PrematureChildProcessExitError;
9-
use hermes_tokio_runtime_components::impls::os::exec_command::ExecCommandFailure;
9+
use hermes_tokio_runtime_components::impls::os::exec_command::{
10+
CommandNotFound, ExecCommandFailure,
11+
};
1012

1113
use crate::impls::runtime::components::HermesRuntimeComponents;
1214
use crate::types::error::TokioRuntimeError;
@@ -60,3 +62,9 @@ impl ErrorRaiser<HermesRuntime, ExecCommandFailure> for HermesRuntimeComponents
6062
}
6163
}
6264
}
65+
66+
impl ErrorRaiser<HermesRuntime, CommandNotFound> for HermesRuntimeComponents {
67+
fn raise_error(e: CommandNotFound) -> TokioRuntimeError {
68+
TokioRuntimeError::CommandNotFound { command: e.command }
69+
}
70+
}

crates/runtime/runtime/src/types/error.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use alloc::sync::Arc;
2-
use core::fmt::Display;
2+
use core::fmt::{Debug, Display};
33
use core::str::Utf8Error;
44
use std::error::Error;
55
use std::io::Error as IoError;
66
use std::process::ExitStatus;
77

8-
#[derive(Clone, Debug)]
8+
#[derive(Clone)]
99
pub enum TokioRuntimeError {
1010
ChannelClosed,
1111
PoisonedLock,
@@ -25,6 +25,9 @@ pub enum TokioRuntimeError {
2525
stdout: String,
2626
stderr: String,
2727
},
28+
CommandNotFound {
29+
command: String,
30+
},
2831
}
2932

3033
impl Display for TokioRuntimeError {
@@ -68,10 +71,23 @@ impl Display for TokioRuntimeError {
6871
exit_status
6972
)?;
7073
}
74+
Self::CommandNotFound { command } => {
75+
write!(
76+
f,
77+
"failed to execute command due to command not found: {}",
78+
command
79+
)?;
80+
}
7181
};
7282

7383
Ok(())
7484
}
7585
}
7686

87+
impl Debug for TokioRuntimeError {
88+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
89+
write!(f, "{self}")
90+
}
91+
}
92+
7793
impl Error for TokioRuntimeError {}

crates/runtime/tokio-runtime-components/src/impls/os/exec_command.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::str;
22
use core::str::Utf8Error;
33
use std::ffi::OsStr;
4-
use std::io::Error as IoError;
4+
use std::io::{Error as IoError, ErrorKind};
55

66
use cgp::prelude::*;
77
use hermes_runtime_components::traits::fs::file_path::HasFilePathType;
@@ -17,11 +17,16 @@ pub struct ExecCommandFailure {
1717
pub stderr: String,
1818
}
1919

20+
pub struct CommandNotFound {
21+
pub command: String,
22+
}
23+
2024
impl<Runtime> CommandWithEnvsExecutor<Runtime> for TokioExecCommand
2125
where
2226
Runtime: HasFilePathType
2327
+ CanRaiseError<IoError>
2428
+ CanRaiseError<Utf8Error>
29+
+ CanRaiseError<CommandNotFound>
2530
+ CanRaiseError<ExecCommandFailure>,
2631
Runtime::FilePath: AsRef<OsStr>,
2732
{
@@ -37,7 +42,15 @@ where
3742
.kill_on_drop(true)
3843
.output()
3944
.await
40-
.map_err(Runtime::raise_error)?;
45+
.map_err(|e| {
46+
if e.kind() == ErrorKind::NotFound {
47+
Runtime::raise_error(CommandNotFound {
48+
command: Runtime::file_path_to_string(command_path),
49+
})
50+
} else {
51+
Runtime::raise_error(e)
52+
}
53+
})?;
4154

4255
let stdout = str::from_utf8(&output.stdout).map_err(Runtime::raise_error)?;
4356

0 commit comments

Comments
 (0)