This commit is contained in:
despiegk 2025-04-04 18:38:53 +02:00
parent c9b4010089
commit bf5eb2f6fc
10 changed files with 198 additions and 29 deletions

View File

View File

View File

View File

View File

@ -19,10 +19,13 @@ let file_content = "This is a test file created by Rhai script.";
println(`Creating file: ${test_file}`); println(`Creating file: ${test_file}`);
// First ensure the directory exists // First ensure the directory exists
run_command(`mkdir -p ${test_dir}`); run_command(`mkdir -p ${test_dir}`);
// Then create the file using a different approach // Then create the file using a simpler approach
// Use run_command with sh -c to properly handle shell features // First touch the file
let write_cmd = `sh -c 'touch ${test_file} && echo "${file_content}" > ${test_file}'`; let touch_cmd = `touch ${test_file}`;
let write_result = run_command(write_cmd); 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}`); println(`File creation result: ${write_result.success}`);
// Wait a moment to ensure the file is created // Wait a moment to ensure the file is created

View File

@ -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!"

View File

@ -16,7 +16,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.short("p") .short("p")
.long("path") .long("path")
.value_name("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) .required(true)
.takes_value(true), .takes_value(true),
) )

View File

@ -14,17 +14,17 @@ use std::process;
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `script_path` - Path to the directory containing Rhai scripts /// * `script_path` - Path to a Rhai script file or directory containing Rhai scripts
/// ///
/// # Returns /// # Returns
/// ///
/// Result indicating success or failure /// Result indicating success or failure
pub fn run(script_path: &str) -> Result<(), Box<dyn Error>> { pub fn run(script_path: &str) -> Result<(), Box<dyn Error>> {
let script_dir = Path::new(script_path); let path = Path::new(script_path);
// Check if the directory exists // Check if the path exists
if !script_dir.exists() || !script_dir.is_dir() { if !path.exists() {
eprintln!("Error: '{}' is not a valid directory", script_path); eprintln!("Error: '{}' does not exist", script_path);
process::exit(1); process::exit(1);
} }
@ -37,25 +37,57 @@ pub fn run(script_path: &str) -> Result<(), Box<dyn Error>> {
// Register all SAL modules with the engine // Register all SAL modules with the engine
crate::rhai::register(&mut engine)?; crate::rhai::register(&mut engine)?;
// Find all .rhai files in the directory // Determine if the path is a file or directory
let mut script_files: Vec<PathBuf> = fs::read_dir(script_dir)? let script_files: Vec<PathBuf> = if path.is_file() {
.filter_map(Result::ok) // Check if it's a .rhai file
.filter(|entry| { if path.extension().map_or(false, |ext| ext == "rhai") {
entry.path().is_file() && vec![path.to_path_buf()]
entry.path().extension().map_or(false, |ext| ext == "rhai") } else {
}) eprintln!("Error: '{}' is not a Rhai script file", script_path);
.map(|entry| entry.path()) process::exit(1);
.collect(); }
} else if path.is_dir() {
// Find all .rhai files in the directory recursively
let mut files: Vec<PathBuf> = Vec::new();
// Helper function to recursively find .rhai files
fn find_rhai_files(dir: &Path, files: &mut Vec<PathBuf>) -> 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 // Sort the script files by name
script_files.sort(); files.sort();
if script_files.is_empty() { if files.is_empty() {
println!("No Rhai scripts found in '{}'", script_path); println!("No Rhai scripts found in '{}'", script_path);
return Ok(()); return Ok(());
} }
println!("Found {} Rhai scripts to execute:", script_files.len()); files
} else {
eprintln!("Error: '{}' is neither a file nor a directory", script_path);
process::exit(1);
};
println!("Found {} Rhai script{} to execute:",
script_files.len(),
if script_files.len() == 1 { "" } else { "s" });
// Execute each script in sorted order // Execute each script in sorted order
for script_file in script_files { for script_file in script_files {
@ -74,7 +106,8 @@ pub fn run(script_path: &str) -> Result<(), Box<dyn Error>> {
}, },
Err(err) => { Err(err) => {
eprintln!("Error executing script: {}", 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);
} }
} }
} }

View File

@ -20,6 +20,7 @@ pub enum FsError {
NotAFile(String), NotAFile(String),
UnknownFileType(String), UnknownFileType(String),
MetadataError(io::Error), MetadataError(io::Error),
ChangeDirFailed(io::Error),
} }
// Implement Display for FsError // 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::NotAFile(path) => write!(f, "Path '{}' is not a regular file", path),
FsError::UnknownFileType(path) => write!(f, "Unknown file type at '{}'", path), FsError::UnknownFileType(path) => write!(f, "Unknown file type at '{}'", path),
FsError::MetadataError(e) => write!(f, "Failed to get file metadata: {}", e), 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::CommandExecutionError(e) => Some(e),
FsError::InvalidGlobPattern(e) => Some(e), FsError::InvalidGlobPattern(e) => Some(e),
FsError::MetadataError(e) => Some(e), FsError::MetadataError(e) => Some(e),
FsError::ChangeDirFailed(e) => Some(e),
_ => None, _ => None,
} }
} }
@ -578,3 +581,41 @@ pub fn rsync(src: &str, dest: &str) -> Result<String, FsError> {
Err(e) => Err(FsError::CommandExecutionError(e)), 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<String, FsError> {
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))
}

View File

@ -30,6 +30,7 @@ pub fn register_os_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>>
engine.register_fn("mkdir", mkdir); engine.register_fn("mkdir", mkdir);
engine.register_fn("file_size", file_size); engine.register_fn("file_size", file_size);
engine.register_fn("rsync", rsync); engine.register_fn("rsync", rsync);
engine.register_fn("chdir", chdir);
// Register download functions // Register download functions
engine.register_fn("download", download); engine.register_fn("download", download);
@ -128,6 +129,13 @@ pub fn rsync(src: &str, dest: &str) -> Result<String, Box<EvalAltResult>> {
os::rsync(src, dest).to_rhai_error() os::rsync(src, dest).to_rhai_error()
} }
/// Wrapper for os::chdir
///
/// Change the current working directory.
pub fn chdir(path: &str) -> Result<String, Box<EvalAltResult>> {
os::chdir(path).to_rhai_error()
}
// //
// Download Function Wrappers // Download Function Wrappers
// //