diff --git a/Cargo.lock b/Cargo.lock index 84f3629..1404326 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -913,6 +913,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "platform-info" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5ff316b9c4642feda973c18f0decd6c8b0919d4722566f6e4337cce0dd88217" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "pretty_assertions" version = "1.4.0" @@ -1091,6 +1101,8 @@ dependencies = [ "rustyline", "tokio", "uu_ls", + "uu_uname", + "which", ] [[package]] @@ -1322,6 +1334,17 @@ dependencies = [ "uutils_term_grid", ] +[[package]] +name = "uu_uname" +version = "0.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1ca90f9b292bccaad0de70e6feccac5182c6713a5e1ca72d97bf3555b608b4" +dependencies = [ + "clap", + "platform-info", + "uucore", +] + [[package]] name = "uucore" version = "0.0.27" @@ -1437,6 +1460,18 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + [[package]] name = "wild" version = "2.2.1" @@ -1446,6 +1481,22 @@ dependencies = [ "glob", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -1455,6 +1506,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows" version = "0.52.0" @@ -1622,6 +1679,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "xattr" version = "1.3.1" diff --git a/crates/shell/Cargo.toml b/crates/shell/Cargo.toml index a48bbe5..61413a7 100644 --- a/crates/shell/Cargo.toml +++ b/crates/shell/Cargo.toml @@ -27,6 +27,8 @@ rustyline = { version = "14.0.0", features = ["derive"] } tokio = "1.40.0" uu_ls = "0.0.27" dirs = "5.0.1" +which = "6.0.3" +uu_uname = "0.0.27" [package.metadata.release] # Dont publish the binary diff --git a/crates/shell/src/commands.rs b/crates/shell/src/commands/mod.rs similarity index 97% rename from crates/shell/src/commands.rs rename to crates/shell/src/commands/mod.rs index 5304be2..5918a6e 100644 --- a/crates/shell/src/commands.rs +++ b/crates/shell/src/commands/mod.rs @@ -6,6 +6,13 @@ use futures::{future::LocalBoxFuture, FutureExt}; use uu_ls::uumain as uu_ls; use crate::execute; + +pub mod uname; +pub mod which; + +pub use uname::UnameCommand; +pub use which::WhichCommand; + pub struct LsCommand; pub struct AliasCommand; diff --git a/crates/shell/src/commands/uname.rs b/crates/shell/src/commands/uname.rs new file mode 100644 index 0000000..0d956ba --- /dev/null +++ b/crates/shell/src/commands/uname.rs @@ -0,0 +1,54 @@ +use deno_task_shell::{ExecuteResult, ShellCommand, ShellCommandContext}; +use futures::future::LocalBoxFuture; +use uu_uname::{options, UNameOutput}; +pub struct UnameCommand; + +fn display(uname: &UNameOutput) -> String { + let mut output = String::new(); + for name in [ + uname.kernel_name.as_ref(), + uname.nodename.as_ref(), + uname.kernel_release.as_ref(), + uname.kernel_version.as_ref(), + uname.machine.as_ref(), + uname.os.as_ref(), + uname.processor.as_ref(), + uname.hardware_platform.as_ref(), + ] + .into_iter() + .flatten() + { + output.push_str(name); + output.push(' '); + } + output +} + +impl ShellCommand for UnameCommand { + fn execute(&self, mut context: ShellCommandContext) -> LocalBoxFuture<'static, ExecuteResult> { + let matches = uu_uname::uu_app() + .no_binary_name(true) + .try_get_matches_from(context.args) + .unwrap(); + + let options = uu_uname::Options { + all: matches.get_flag(options::ALL), + kernel_name: matches.get_flag(options::KERNEL_NAME), + nodename: matches.get_flag(options::NODENAME), + kernel_release: matches.get_flag(options::KERNEL_RELEASE), + kernel_version: matches.get_flag(options::KERNEL_VERSION), + machine: matches.get_flag(options::MACHINE), + processor: matches.get_flag(options::PROCESSOR), + hardware_platform: matches.get_flag(options::HARDWARE_PLATFORM), + os: matches.get_flag(options::OS), + }; + + let uname = UNameOutput::new(&options).unwrap(); + context + .stdout + .write_line(display(&uname).trim_end()) + .unwrap(); + + Box::pin(futures::future::ready(ExecuteResult::from_exit_code(0))) + } +} diff --git a/crates/shell/src/commands/which.rs b/crates/shell/src/commands/which.rs new file mode 100644 index 0000000..ac796ad --- /dev/null +++ b/crates/shell/src/commands/which.rs @@ -0,0 +1,48 @@ +use deno_task_shell::{ExecuteResult, ShellCommand, ShellCommandContext}; +use futures::future::LocalBoxFuture; + +pub struct WhichCommand; + +impl ShellCommand for WhichCommand { + fn execute(&self, context: ShellCommandContext) -> LocalBoxFuture<'static, ExecuteResult> { + Box::pin(futures::future::ready(execute_which(context))) + } +} + +fn execute_which(mut context: ShellCommandContext) -> ExecuteResult { + if context.args.len() != 1 { + context.stderr.write_line("Expected one argument.").unwrap(); + return ExecuteResult::from_exit_code(1); + } + let arg = &context.args[0]; + + if let Some(alias) = context.state.alias_map().get(arg) { + context + .stdout + .write_line(&format!("alias: \"{}\"", alias.join(" "))) + .unwrap(); + return ExecuteResult::from_exit_code(0); + } + + if context.state.resolve_custom_command(arg).is_some() { + context.stdout.write_line("").unwrap(); + return ExecuteResult::from_exit_code(0); + } + + if let Some(path) = context.state.env_vars().get("PATH") { + let path = std::ffi::OsString::from(path); + let which_result = which::which_in_global(arg, Some(path)) + .and_then(|mut i| i.next().ok_or(which::Error::CannotFindBinaryPath)); + + if let Ok(p) = which_result { + context.stdout.write_line(&p.to_string_lossy()).unwrap(); + return ExecuteResult::from_exit_code(0); + } + } + + context + .stderr + .write_line(&format!("{} not found", arg)) + .unwrap(); + ExecuteResult::from_exit_code(1) +} diff --git a/crates/shell/src/main.rs b/crates/shell/src/main.rs index 8bcebbf..6b5af5f 100644 --- a/crates/shell/src/main.rs +++ b/crates/shell/src/main.rs @@ -34,6 +34,14 @@ fn commands() -> HashMap> { "source".to_string(), Rc::new(commands::SourceCommand) as Rc, ), + ( + "which".to_string(), + Rc::new(commands::WhichCommand) as Rc, + ), + ( + "uname".to_string(), + Rc::new(commands::UnameCommand) as Rc, + ), ]) }