//! Rhai wrappers for OS module functions //! //! This module provides Rhai wrappers for the functions in the OS module. use crate::package::PackHero; use crate::{download as dl, fs, package}; use rhai::{Array, Engine, EvalAltResult, Position}; /// A trait for converting a Result to a Rhai-compatible error pub trait ToRhaiError { fn to_rhai_error(self) -> Result>; } impl ToRhaiError for Result { fn to_rhai_error(self) -> Result> { self.map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( e.to_string().into(), Position::NONE, )) }) } } /// Register OS module functions with the Rhai engine /// /// # Arguments /// /// * `engine` - The Rhai engine to register the functions with /// /// # Returns /// /// * `Result<(), Box>` - Ok if registration was successful, Err otherwise pub fn register_os_module(engine: &mut Engine) -> Result<(), Box> { // Register file system functions engine.register_fn("copy", copy); engine.register_fn("copy_bin", copy_bin); engine.register_fn("exist", exist); engine.register_fn("find_file", find_file); engine.register_fn("find_files", find_files); engine.register_fn("find_dir", find_dir); engine.register_fn("find_dirs", find_dirs); engine.register_fn("delete", delete); engine.register_fn("mkdir", mkdir); engine.register_fn("file_size", file_size); engine.register_fn("rsync", rsync); engine.register_fn("chdir", chdir); engine.register_fn("file_read", file_read); engine.register_fn("file_write", file_write); engine.register_fn("file_write_append", file_write_append); // Register command check functions engine.register_fn("which", which); engine.register_fn("cmd_ensure_exists", cmd_ensure_exists); // Register download functions engine.register_fn("download", download); engine.register_fn("download_file", download_file); engine.register_fn("download_install", download_install); engine.register_fn("chmod_exec", chmod_exec); // Register move function engine.register_fn("mv", mv); // Register package management functions engine.register_fn("package_install", package_install); engine.register_fn("package_remove", package_remove); engine.register_fn("package_update", package_update); engine.register_fn("package_upgrade", package_upgrade); engine.register_fn("package_list", package_list); engine.register_fn("package_search", package_search); engine.register_fn("package_is_installed", package_is_installed); engine.register_fn("package_set_debug", package_set_debug); engine.register_fn("package_platform", package_platform); // Register platform detection functions engine.register_fn("platform_is_osx", platform_is_osx); engine.register_fn("platform_is_linux", platform_is_linux); engine.register_fn("platform_is_arm", platform_is_arm); engine.register_fn("platform_is_x86", platform_is_x86); engine.register_fn("platform_check_linux_x86", platform_check_linux_x86); engine.register_fn("platform_check_macos_arm", platform_check_macos_arm); Ok(()) } // // File System Function Wrappers // /// Wrapper for fs::copy /// /// Recursively copy a file or directory from source to destination. pub fn copy(src: &str, dest: &str) -> Result> { fs::copy(src, dest).to_rhai_error() } /// Wrapper for fs::copy_bin /// /// Copy a binary to the correct location based on OS and user privileges. pub fn copy_bin(src: &str) -> Result> { fs::copy_bin(src).to_rhai_error() } /// Wrapper for fs::exist /// /// Check if a file or directory exists. pub fn exist(path: &str) -> bool { fs::exist(path) } /// Wrapper for fs::find_file /// /// Find a file in a directory (with support for wildcards). pub fn find_file(dir: &str, filename: &str) -> Result> { fs::find_file(dir, filename).to_rhai_error() } /// Wrapper for fs::find_files /// /// Find multiple files in a directory (recursive, with support for wildcards). pub fn find_files(dir: &str, filename: &str) -> Result> { let files = fs::find_files(dir, filename).to_rhai_error()?; // Convert Vec to Rhai Array let mut array = Array::new(); for file in files { array.push(file.into()); } Ok(array) } /// Wrapper for fs::find_dir /// /// Find a directory in a parent directory (with support for wildcards). pub fn find_dir(dir: &str, dirname: &str) -> Result> { fs::find_dir(dir, dirname).to_rhai_error() } /// Wrapper for fs::find_dirs /// /// Find multiple directories in a parent directory (recursive, with support for wildcards). pub fn find_dirs(dir: &str, dirname: &str) -> Result> { let dirs = fs::find_dirs(dir, dirname).to_rhai_error()?; // Convert Vec to Rhai Array let mut array = Array::new(); for dir in dirs { array.push(dir.into()); } Ok(array) } /// Wrapper for fs::delete /// /// Delete a file or directory (defensive - doesn't error if file doesn't exist). pub fn delete(path: &str) -> Result> { fs::delete(path).to_rhai_error() } /// Wrapper for fs::mkdir /// /// Create a directory and all parent directories (defensive - doesn't error if directory exists). pub fn mkdir(path: &str) -> Result> { fs::mkdir(path).to_rhai_error() } /// Wrapper for fs::file_size /// /// Get the size of a file in bytes. pub fn file_size(path: &str) -> Result> { fs::file_size(path).to_rhai_error() } /// Wrapper for fs::rsync /// /// Sync directories using rsync (or platform equivalent). pub fn rsync(src: &str, dest: &str) -> Result> { fs::rsync(src, dest).to_rhai_error() } /// Wrapper for fs::chdir /// /// Change the current working directory. pub fn chdir(path: &str) -> Result> { fs::chdir(path).to_rhai_error() } /// Wrapper for fs::file_read /// /// Read the contents of a file. pub fn file_read(path: &str) -> Result> { fs::file_read(path).to_rhai_error() } /// Wrapper for fs::file_write /// /// Write content to a file (creates the file if it doesn't exist, overwrites if it does). pub fn file_write(path: &str, content: &str) -> Result> { fs::file_write(path, content).to_rhai_error() } /// Wrapper for fs::file_write_append /// /// Append content to a file (creates the file if it doesn't exist). pub fn file_write_append(path: &str, content: &str) -> Result> { fs::file_write_append(path, content).to_rhai_error() } /// Wrapper for fs::mv /// /// Move a file or directory from source to destination. pub fn mv(src: &str, dest: &str) -> Result> { fs::mv(src, dest).to_rhai_error() } // // Download Function Wrappers // /// Wrapper for os::download /// /// Download a file from URL to destination using the curl command. pub fn download(url: &str, dest: &str, min_size_kb: i64) -> Result> { dl::download(url, dest, min_size_kb).to_rhai_error() } /// Wrapper for os::download_file /// /// Download a file from URL to a specific file destination using the curl command. pub fn download_file( url: &str, dest: &str, min_size_kb: i64, ) -> Result> { dl::download_file(url, dest, min_size_kb).to_rhai_error() } /// Wrapper for os::download_install /// /// Download a file and install it if it's a supported package format. pub fn download_install(url: &str, min_size_kb: i64) -> Result> { dl::download_install(url, min_size_kb).to_rhai_error() } /// Wrapper for os::chmod_exec /// /// Make a file executable (equivalent to chmod +x). pub fn chmod_exec(path: &str) -> Result> { dl::chmod_exec(path).to_rhai_error() } /// Wrapper for os::which /// /// Check if a command exists in the system PATH. pub fn which(command: &str) -> String { fs::which(command) } /// Wrapper for os::cmd_ensure_exists /// /// Ensure that one or more commands exist in the system PATH. /// If any command doesn't exist, an error is thrown. pub fn cmd_ensure_exists(commands: &str) -> Result> { fs::cmd_ensure_exists(commands).to_rhai_error() } // // Package Management Function Wrappers // /// Wrapper for os::package::PackHero::install /// /// Install a package using the system package manager. pub fn package_install(package: &str) -> Result> { let hero = PackHero::new(); hero.install(package) .map(|_| format!("Package '{}' installed successfully", package)) .to_rhai_error() } /// Wrapper for os::package::PackHero::remove /// /// Remove a package using the system package manager. pub fn package_remove(package: &str) -> Result> { let hero = PackHero::new(); hero.remove(package) .map(|_| format!("Package '{}' removed successfully", package)) .to_rhai_error() } /// Wrapper for os::package::PackHero::update /// /// Update package lists using the system package manager. pub fn package_update() -> Result> { let hero = PackHero::new(); hero.update() .map(|_| "Package lists updated successfully".to_string()) .to_rhai_error() } /// Wrapper for os::package::PackHero::upgrade /// /// Upgrade installed packages using the system package manager. pub fn package_upgrade() -> Result> { let hero = PackHero::new(); hero.upgrade() .map(|_| "Packages upgraded successfully".to_string()) .to_rhai_error() } /// Wrapper for os::package::PackHero::list_installed /// /// List installed packages using the system package manager. pub fn package_list() -> Result> { let hero = PackHero::new(); let packages = hero.list_installed().to_rhai_error()?; // Convert Vec to Rhai Array let mut array = Array::new(); for package in packages { array.push(package.into()); } Ok(array) } /// Wrapper for os::package::PackHero::search /// /// Search for packages using the system package manager. pub fn package_search(query: &str) -> Result> { let hero = PackHero::new(); let packages = hero.search(query).to_rhai_error()?; // Convert Vec to Rhai Array let mut array = Array::new(); for package in packages { array.push(package.into()); } Ok(array) } /// Wrapper for os::package::PackHero::is_installed /// /// Check if a package is installed using the system package manager. pub fn package_is_installed(package: &str) -> Result> { let hero = PackHero::new(); hero.is_installed(package).to_rhai_error() } // Thread-local storage for package debug flag thread_local! { static PACKAGE_DEBUG: std::cell::RefCell = std::cell::RefCell::new(false); } /// Set the debug mode for package management operations pub fn package_set_debug(debug: bool) -> bool { let mut hero = PackHero::new(); hero.set_debug(debug); // Also set the thread-local debug flag PACKAGE_DEBUG.with(|cell| { *cell.borrow_mut() = debug; }); debug } /// Get the current platform name for package management pub fn package_platform() -> String { let hero = PackHero::new(); match hero.platform() { package::Platform::Ubuntu => "Ubuntu".to_string(), package::Platform::MacOS => "MacOS".to_string(), package::Platform::Unknown => "Unknown".to_string(), } } // // Platform Detection Function Wrappers // /// Wrapper for platform::is_osx pub fn platform_is_osx() -> bool { crate::platform::is_osx() } /// Wrapper for platform::is_linux pub fn platform_is_linux() -> bool { crate::platform::is_linux() } /// Wrapper for platform::is_arm pub fn platform_is_arm() -> bool { crate::platform::is_arm() } /// Wrapper for platform::is_x86 pub fn platform_is_x86() -> bool { crate::platform::is_x86() } /// Wrapper for platform::check_linux_x86 pub fn platform_check_linux_x86() -> Result<(), Box> { crate::platform::check_linux_x86().map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( format!("Platform Check Error: {}", e).into(), Position::NONE, )) }) } /// Wrapper for platform::check_macos_arm pub fn platform_check_macos_arm() -> Result<(), Box> { crate::platform::check_macos_arm().map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( format!("Platform Check Error: {}", e).into(), Position::NONE, )) }) }