From bf5eb2f6fc91bfe9a2b6b2a1e399476d4ae87089 Mon Sep 17 00:00:00 2001 From: despiegk Date: Fri, 4 Apr 2025 18:38:53 +0200 Subject: [PATCH] ... --- rhai_dir_test/base_file.txt | 0 rhai_dir_test/tmp/test/sub_file.txt | 0 rhai_test_dir/copied_file.txt | 0 rhai_test_dir/test_file.txt | 0 rhaiexamples/02_file_operations.rhai | 11 +-- rhaiexamples/05_directory_operations.rhai | 84 +++++++++++++++++++++++ src/bin/herodo.rs | 2 +- src/cmd/herodo.rs | 81 +++++++++++++++------- src/os/fs.rs | 41 +++++++++++ src/rhai/os.rs | 8 +++ 10 files changed, 198 insertions(+), 29 deletions(-) create mode 100644 rhai_dir_test/base_file.txt create mode 100644 rhai_dir_test/tmp/test/sub_file.txt create mode 100644 rhai_test_dir/copied_file.txt create mode 100644 rhai_test_dir/test_file.txt create mode 100644 rhaiexamples/05_directory_operations.rhai diff --git a/rhai_dir_test/base_file.txt b/rhai_dir_test/base_file.txt new file mode 100644 index 0000000..e69de29 diff --git a/rhai_dir_test/tmp/test/sub_file.txt b/rhai_dir_test/tmp/test/sub_file.txt new file mode 100644 index 0000000..e69de29 diff --git a/rhai_test_dir/copied_file.txt b/rhai_test_dir/copied_file.txt new file mode 100644 index 0000000..e69de29 diff --git a/rhai_test_dir/test_file.txt b/rhai_test_dir/test_file.txt new file mode 100644 index 0000000..e69de29 diff --git a/rhaiexamples/02_file_operations.rhai b/rhaiexamples/02_file_operations.rhai index 0c96e0d..3c72d13 100644 --- a/rhaiexamples/02_file_operations.rhai +++ b/rhaiexamples/02_file_operations.rhai @@ -19,10 +19,13 @@ let file_content = "This is a test file created by Rhai script."; println(`Creating file: ${test_file}`); // First ensure the directory exists run_command(`mkdir -p ${test_dir}`); -// Then create the file using a different approach -// Use run_command with sh -c to properly handle shell features -let write_cmd = `sh -c 'touch ${test_file} && echo "${file_content}" > ${test_file}'`; -let write_result = run_command(write_cmd); +// Then create the file using a simpler approach +// First touch the file +let touch_cmd = `touch ${test_file}`; +run_command(touch_cmd); +// Then write to it with a separate command +let echo_cmd = `echo ${file_content} > ${test_file}`; +let write_result = run_command(echo_cmd); println(`File creation result: ${write_result.success}`); // Wait a moment to ensure the file is created diff --git a/rhaiexamples/05_directory_operations.rhai b/rhaiexamples/05_directory_operations.rhai new file mode 100644 index 0000000..453f651 --- /dev/null +++ b/rhaiexamples/05_directory_operations.rhai @@ -0,0 +1,84 @@ +// 05_directory_operations.rhai +// Demonstrates directory operations using SAL, including the new chdir function + +// Create a test directory structure +let base_dir = "rhai_dir_test"; +let sub_dir = base_dir + "/tmp/test"; + +println("Creating directory structure..."); +let base_result = mkdir(base_dir+"/subdir"); +println(`Base directory creation result: ${base_result}`); + +let sub_result = mkdir(sub_dir); +println(`Subdirectory creation result: ${sub_result}`); + +// Create a test file in the base directory +let base_file = base_dir + "/base_file.txt"; +let base_content = "This is a file in the base directory."; +// First touch the file +run_command(`touch ${base_file}`); +// Then write to it with a separate command +run_command(`echo ${base_content} > ${base_file}`); + +// Create a test file in the subdirectory +let sub_file = sub_dir + "/sub_file.txt"; +let sub_content = "This is a file in the subdirectory."; +// First touch the file +run_command(`touch ${sub_file}`); +// Then write to it with a separate command +run_command(`echo ${sub_content} > ${sub_file}`); + +// Get the current working directory before changing +let pwd_before = run_command("pwd"); +println(`Current directory before chdir: ${pwd_before.stdout.trim()}`); + +// Change to the base directory +println(`Changing directory to: ${base_dir}`); +let chdir_result = chdir(base_dir); +println(`Directory change result: ${chdir_result}`); + +// Get the current working directory after changing +let pwd_after = run_command("pwd"); +println(`Current directory after chdir: ${pwd_after.stdout.trim()}`); + +// List files in the current directory (which should now be the base directory) +println("Files in the current directory:"); +let files = find_files(".", "*"); +println("Files found:"); +for file in files { + println(`- ${file}`); +} + +// Change to the subdirectory +println(`Changing directory to: subdir`); +let chdir_sub_result = chdir("subdir"); +println(`Directory change result: ${chdir_sub_result}`); + +// Get the current working directory after changing to subdirectory +let pwd_final = run_command("pwd"); +println(`Current directory after second chdir: ${pwd_final.stdout.trim()}`); + +// List files in the subdirectory +println("Files in the subdirectory:"); +let subdir_files = find_files(".", "*"); +println("Files found:"); +for file in subdir_files { + println(`- ${file}`); +} + +// Change back to the parent directory +println("Changing directory back to parent..."); +let chdir_parent_result = chdir(".."); +println(`Directory change result: ${chdir_parent_result}`); + +// Clean up (uncomment to actually delete the files) +// println("Cleaning up..."); +// Change back to the original directory first +// chdir(pwd_before.stdout.trim()); +// delete(sub_file); +// delete(base_file); +// delete(sub_dir); +// delete(base_dir); +// println("Cleanup complete"); + +"Directory operations script completed successfully!" \ No newline at end of file diff --git a/src/bin/herodo.rs b/src/bin/herodo.rs index 8061af6..f1a5491 100644 --- a/src/bin/herodo.rs +++ b/src/bin/herodo.rs @@ -16,7 +16,7 @@ fn main() -> Result<(), Box> { .short("p") .long("path") .value_name("PATH") - .help("Path to directory containing Rhai scripts") + .help("Path to a Rhai script file or directory containing Rhai scripts") .required(true) .takes_value(true), ) diff --git a/src/cmd/herodo.rs b/src/cmd/herodo.rs index 310cb31..26c7c60 100644 --- a/src/cmd/herodo.rs +++ b/src/cmd/herodo.rs @@ -14,17 +14,17 @@ use std::process; /// /// # Arguments /// -/// * `script_path` - Path to the directory containing Rhai scripts +/// * `script_path` - Path to a Rhai script file or directory containing Rhai scripts /// /// # Returns /// /// Result indicating success or failure pub fn run(script_path: &str) -> Result<(), Box> { - let script_dir = Path::new(script_path); + let path = Path::new(script_path); - // Check if the directory exists - if !script_dir.exists() || !script_dir.is_dir() { - eprintln!("Error: '{}' is not a valid directory", script_path); + // Check if the path exists + if !path.exists() { + eprintln!("Error: '{}' does not exist", script_path); process::exit(1); } @@ -37,25 +37,57 @@ pub fn run(script_path: &str) -> Result<(), Box> { // Register all SAL modules with the engine crate::rhai::register(&mut engine)?; - // Find all .rhai files in the directory - let mut script_files: Vec = fs::read_dir(script_dir)? - .filter_map(Result::ok) - .filter(|entry| { - entry.path().is_file() && - entry.path().extension().map_or(false, |ext| ext == "rhai") - }) - .map(|entry| entry.path()) - .collect(); + // Determine if the path is a file or directory + let script_files: Vec = if path.is_file() { + // Check if it's a .rhai file + if path.extension().map_or(false, |ext| ext == "rhai") { + vec![path.to_path_buf()] + } else { + eprintln!("Error: '{}' is not a Rhai script file", script_path); + process::exit(1); + } + } else if path.is_dir() { + // Find all .rhai files in the directory recursively + let mut files: Vec = Vec::new(); + + // Helper function to recursively find .rhai files + fn find_rhai_files(dir: &Path, files: &mut Vec) -> std::io::Result<()> { + if dir.is_dir() { + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + + if path.is_dir() { + find_rhai_files(&path, files)?; + } else if path.is_file() && + path.extension().map_or(false, |ext| ext == "rhai") { + files.push(path); + } + } + } + Ok(()) + } + + // Find all .rhai files recursively + find_rhai_files(path, &mut files)?; + + // Sort the script files by name + files.sort(); + + if files.is_empty() { + println!("No Rhai scripts found in '{}'", script_path); + return Ok(()); + } + + files + } else { + eprintln!("Error: '{}' is neither a file nor a directory", script_path); + process::exit(1); + }; - // Sort the script files by name - script_files.sort(); - - if script_files.is_empty() { - println!("No Rhai scripts found in '{}'", script_path); - return Ok(()); - } - - println!("Found {} Rhai scripts to execute:", script_files.len()); + println!("Found {} Rhai script{} to execute:", + script_files.len(), + if script_files.len() == 1 { "" } else { "s" }); // Execute each script in sorted order for script_file in script_files { @@ -74,7 +106,8 @@ pub fn run(script_path: &str) -> Result<(), Box> { }, Err(err) => { eprintln!("Error executing script: {}", err); - // Continue with the next script instead of stopping + // Exit with error code when a script fails + process::exit(1); } } } diff --git a/src/os/fs.rs b/src/os/fs.rs index d848464..c225a34 100644 --- a/src/os/fs.rs +++ b/src/os/fs.rs @@ -20,6 +20,7 @@ pub enum FsError { NotAFile(String), UnknownFileType(String), MetadataError(io::Error), + ChangeDirFailed(io::Error), } // Implement Display for FsError @@ -38,6 +39,7 @@ impl fmt::Display for FsError { FsError::NotAFile(path) => write!(f, "Path '{}' is not a regular file", path), FsError::UnknownFileType(path) => write!(f, "Unknown file type at '{}'", path), FsError::MetadataError(e) => write!(f, "Failed to get file metadata: {}", e), + FsError::ChangeDirFailed(e) => write!(f, "Failed to change directory: {}", e), } } } @@ -52,6 +54,7 @@ impl Error for FsError { FsError::CommandExecutionError(e) => Some(e), FsError::InvalidGlobPattern(e) => Some(e), FsError::MetadataError(e) => Some(e), + FsError::ChangeDirFailed(e) => Some(e), _ => None, } } @@ -578,3 +581,41 @@ pub fn rsync(src: &str, dest: &str) -> Result { Err(e) => Err(FsError::CommandExecutionError(e)), } } + +/** + * Change the current working directory. + * + * # Arguments + * + * * `path` - The path to change to + * + * # Returns + * + * * `Ok(String)` - A success message indicating the directory was changed + * * `Err(FsError)` - An error if the directory change failed + * + * # Examples + * + * ``` + * let result = chdir("/path/to/directory")?; + * println!("{}", result); + * ``` + */ +pub fn chdir(path: &str) -> Result { + let path_obj = Path::new(path); + + // Check if directory exists + if !path_obj.exists() { + return Err(FsError::DirectoryNotFound(path.to_string())); + } + + // Check if it's a directory + if !path_obj.is_dir() { + return Err(FsError::NotADirectory(path.to_string())); + } + + // Change directory + std::env::set_current_dir(path_obj).map_err(FsError::ChangeDirFailed)?; + + Ok(format!("Successfully changed directory to '{}'", path)) +} diff --git a/src/rhai/os.rs b/src/rhai/os.rs index 20be388..f32fee9 100644 --- a/src/rhai/os.rs +++ b/src/rhai/os.rs @@ -30,6 +30,7 @@ pub fn register_os_module(engine: &mut Engine) -> Result<(), Box> engine.register_fn("mkdir", mkdir); engine.register_fn("file_size", file_size); engine.register_fn("rsync", rsync); + engine.register_fn("chdir", chdir); // Register download functions engine.register_fn("download", download); @@ -128,6 +129,13 @@ pub fn rsync(src: &str, dest: &str) -> Result> { os::rsync(src, dest).to_rhai_error() } +/// Wrapper for os::chdir +/// +/// Change the current working directory. +pub fn chdir(path: &str) -> Result> { + os::chdir(path).to_rhai_error() +} + // // Download Function Wrappers //