use std::path::Path;
pub fn is_cargo_command(program: &str) -> bool {
let name = Path::new(program)
.file_name()
.and_then(|value| value.to_str())
.unwrap_or(program)
.to_ascii_lowercase();
name == "cargo"
}
pub fn is_cargo_command_string(command: &str) -> bool {
let trimmed = command.trim();
trimmed.starts_with("cargo ") || trimmed == "cargo"
}
const LOCKFILE_COMMANDS: &[&str] = &[
"cargo", "npm", "pnpm", "yarn", "bun", "go", "gradle", "mvn", "pip", "pip3", "poetry", "composer", "bundler", "bundle", ];
fn normalize_program_name(program: &str) -> String {
Path::new(program)
.file_name()
.and_then(|value| value.to_str())
.unwrap_or(program)
.to_ascii_lowercase()
}
pub fn is_lockfile_command(program: &str) -> bool {
let name = normalize_program_name(program);
LOCKFILE_COMMANDS.contains(&name.as_str())
}
pub fn is_long_running_command(program: &str) -> bool {
let name = normalize_program_name(program);
is_development_toolchain_command(&name) || is_lockfile_command(&name)
}
pub fn is_lockfile_command_string(command: &str) -> bool {
let trimmed = command.trim();
LOCKFILE_COMMANDS
.iter()
.any(|&cmd| trimmed.starts_with(&format!("{cmd} ")) || trimmed == cmd)
}
pub fn is_long_running_command_string(command: &str) -> bool {
let trimmed = command.trim();
if trimmed.is_empty() {
return false;
}
if is_lockfile_command_string(trimmed) {
return true;
}
let first = trimmed.split_whitespace().next().unwrap_or_default();
is_development_toolchain_command(first)
}
pub(super) fn is_shell_program(program: &str) -> bool {
let name = Path::new(program)
.file_name()
.and_then(|value| value.to_str())
.unwrap_or(program)
.to_ascii_lowercase();
matches!(
name.as_str(),
"bash" | "sh" | "zsh" | "fish" | "dash" | "ash" | "busybox"
)
}
pub(super) fn is_sandbox_wrapper_program(program: &str, args: &[String]) -> bool {
let name = Path::new(program)
.file_name()
.and_then(|value| value.to_str())
.unwrap_or(program)
.to_ascii_lowercase();
if name == "sandbox-exec" {
return true;
}
args.iter().any(|arg| {
matches!(
arg.as_str(),
"--sandbox-policy" | "--sandbox-policy-cwd" | "--seccomp-profile" | "--resource-limits"
)
})
}
pub fn is_development_toolchain_command(program: &str) -> bool {
let name = Path::new(program)
.file_name()
.and_then(|value| value.to_str())
.unwrap_or(program)
.to_ascii_lowercase();
matches!(
name.as_str(),
"cargo"
| "rustc"
| "rustup"
| "rustfmt"
| "clippy"
| "npm"
| "node"
| "yarn"
| "pnpm"
| "bun"
| "go"
| "python"
| "python3"
| "pip"
| "pip3"
| "java"
| "javac"
| "mvn"
| "gradle"
| "make"
| "cmake"
| "gcc"
| "g++"
| "clang"
| "clang++"
| "which"
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_cargo_command() {
assert!(is_cargo_command("cargo"));
assert!(is_cargo_command("Cargo"));
assert!(is_cargo_command("/usr/bin/cargo"));
assert!(is_cargo_command("~/.cargo/bin/cargo"));
assert!(!is_cargo_command("rustc"));
assert!(!is_cargo_command("npm"));
assert!(!is_cargo_command("cargo-watch"));
}
#[test]
fn test_is_cargo_command_string() {
assert!(is_cargo_command_string("cargo check"));
assert!(is_cargo_command_string("cargo test --lib"));
assert!(is_cargo_command_string("cargo build --release"));
assert!(is_cargo_command_string(" cargo clippy "));
assert!(is_cargo_command_string("cargo"));
assert!(!is_cargo_command_string("rustc --version"));
assert!(!is_cargo_command_string("npm install"));
assert!(!is_cargo_command_string("echo cargo"));
}
#[test]
fn test_is_long_running_command() {
assert!(is_long_running_command("cargo"));
assert!(is_long_running_command("cmake"));
assert!(is_long_running_command("composer"));
assert!(is_long_running_command("bundle"));
assert!(is_long_running_command("poetry"));
assert!(!is_long_running_command("rg"));
}
#[test]
fn test_is_long_running_command_string() {
assert!(is_long_running_command_string("cargo test"));
assert!(is_long_running_command_string(" cmake --build ."));
assert!(is_long_running_command_string("composer install"));
assert!(is_long_running_command_string("bundle exec rake"));
assert!(is_long_running_command_string("poetry install"));
assert!(!is_long_running_command_string("rg \"fn main\" ."));
}
#[test]
fn test_is_sandbox_wrapper_program() {
assert!(is_sandbox_wrapper_program("sandbox-exec", &[]));
assert!(is_sandbox_wrapper_program(
"vtcode-linux-sandbox",
&["--sandbox-policy".to_string()]
));
assert!(!is_sandbox_wrapper_program(
"bash",
&["-lc".to_string(), "ls".to_string()]
));
}
}