Skip to content

Commit

Permalink
fix: exit with code 127 on command not found (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
ruben-arts authored Nov 22, 2023
1 parent d71932b commit 59c27de
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
42 changes: 35 additions & 7 deletions src/shell/commands/executable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ use crate::shell::types::ShellState;
use crate::ExecuteResult;
use crate::ShellCommand;
use crate::ShellCommandContext;
use anyhow::bail;
use anyhow::Result;
use futures::future::LocalBoxFuture;
use futures::FutureExt;

/// Errors for executable commands.
#[derive(Debug, PartialEq)]
enum ExecutableCommandError {
CommandNotFound,
CommandEmpty,
}

/// Command that resolves the command name and
/// executes it in a separate process.
pub struct ExecutableCommand {
Expand All @@ -34,8 +40,14 @@ impl ShellCommand for ExecutableCommand {
Ok(std::env::current_exe()?)
}) {
Ok(command_path) => command_path,
Err(err) => {
let _ = stderr.write_line(&err.to_string());
Err(ExecutableCommandError::CommandNotFound) => {
let _ = stderr
.write_line(&format!("{}: command not found", command_name));
// Use the Exit status that is used in bash: https://www.gnu.org/software/bash/manual/bash.html#Exit-Status
return ExecuteResult::Continue(127, Vec::new(), Vec::new());
}
Err(ExecutableCommandError::CommandEmpty) => {
let _ = stderr.write_line("command name was empty");
return ExecuteResult::Continue(1, Vec::new(), Vec::new());
}
};
Expand Down Expand Up @@ -90,9 +102,9 @@ fn resolve_command_path(
command_name: &str,
state: &ShellState,
current_exe: impl FnOnce() -> Result<PathBuf>,
) -> Result<PathBuf> {
) -> Result<PathBuf, ExecutableCommandError> {
if command_name.is_empty() {
bail!("command name was empty");
return Err(ExecutableCommandError::CommandEmpty);
}

// Special handling to use the current executable for deno.
Expand Down Expand Up @@ -174,8 +186,7 @@ fn resolve_command_path(
}
}
}

bail!("{}: command not found", command_name)
Err(ExecutableCommandError::CommandNotFound)
}

#[cfg(test)]
Expand All @@ -200,4 +211,21 @@ mod local_test {
.unwrap();
assert_eq!(path, PathBuf::from("/bin/deno.exe"));
}

#[test]
fn should_error_on_unknown_command() {
let state = ShellState::new(
Default::default(),
&std::env::current_dir().unwrap(),
Default::default(),
);
// Command not found
let result =
resolve_command_path("foobar", &state, || Ok(PathBuf::from("/bin/deno")));
assert_eq!(result, Err(ExecutableCommandError::CommandNotFound));
// Command empty
let result =
resolve_command_path("", &state, || Ok(PathBuf::from("/bin/deno")));
assert_eq!(result, Err(ExecutableCommandError::CommandEmpty));
}
}
2 changes: 1 addition & 1 deletion src/shell/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ async fn commands() {
.command("deno eval 'console.log(1)'")
.env_var("PATH", "")
.assert_stderr("deno: command not found\n")
.assert_exit_code(1)
.assert_exit_code(127)
.run()
.await;

Expand Down

0 comments on commit 59c27de

Please sign in to comment.