This commit is contained in:
parent
f0d7636cda
commit
0e7dba9466
120
src/os/fs.rs
120
src/os/fs.rs
@ -6,6 +6,8 @@ use std::path::Path;
|
||||
use std::process::Command;
|
||||
use libc;
|
||||
use dirs;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
// Define a custom error type for file system operations
|
||||
#[derive(Debug)]
|
||||
@ -77,39 +79,14 @@ impl Error for FsError {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively copy a file or directory from source to destination.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * `src` - The source path, which can include wildcards
|
||||
* * `dest` - The destination path
|
||||
*
|
||||
* # Returns
|
||||
*
|
||||
* * `Ok(String)` - A success message indicating what was copied
|
||||
* * `Err(FsError)` - An error if the copy operation failed
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```no_run
|
||||
* use sal::os::copy;
|
||||
*
|
||||
* fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
* // Copy a single file
|
||||
* let result = copy("file.txt", "backup/file.txt")?;
|
||||
*
|
||||
* // Copy multiple files using wildcards
|
||||
* let result = copy("*.txt", "backup/")?;
|
||||
*
|
||||
* // Copy a directory recursively
|
||||
* let result = copy("src_dir", "dest_dir")?;
|
||||
*
|
||||
* Ok(())
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
pub fn copy(src: &str, dest: &str) -> Result<String, FsError> {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn set_executable(path: &Path) -> Result<(), io::Error> {
|
||||
let mut perms = fs::metadata(path)?.permissions();
|
||||
perms.set_mode(0o755); // rwxr-xr-x
|
||||
fs::set_permissions(path, perms)
|
||||
}
|
||||
|
||||
fn copy_internal(src: &str, dest: &str, make_executable: bool) -> Result<String, FsError> {
|
||||
let dest_path = Path::new(dest);
|
||||
|
||||
// Check if source path contains wildcards
|
||||
@ -155,6 +132,18 @@ pub fn copy(src: &str, dest: &str) -> Result<String, FsError> {
|
||||
println!("Warning: Failed to copy {}: {}", path.display(), e);
|
||||
} else {
|
||||
success_count += 1;
|
||||
if make_executable {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
if let Err(e) = set_executable(&target_path) {
|
||||
println!(
|
||||
"Warning: Failed to make {} executable: {}",
|
||||
target_path.display(),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if path.is_dir() {
|
||||
// For directories, use platform-specific command
|
||||
@ -225,7 +214,19 @@ pub fn copy(src: &str, dest: &str) -> Result<String, FsError> {
|
||||
if dest_path.exists() && dest_path.is_dir() {
|
||||
let file_name = src_path.file_name().unwrap_or_default();
|
||||
let new_dest_path = dest_path.join(file_name);
|
||||
fs::copy(src_path, new_dest_path).map_err(FsError::CopyFailed)?;
|
||||
fs::copy(src_path, &new_dest_path).map_err(FsError::CopyFailed)?;
|
||||
if make_executable {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
if let Err(e) = set_executable(&new_dest_path) {
|
||||
println!(
|
||||
"Warning: Failed to make {} executable: {}",
|
||||
new_dest_path.display(),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(format!(
|
||||
"Successfully copied file '{}' to '{}/{}'",
|
||||
src,
|
||||
@ -235,6 +236,18 @@ pub fn copy(src: &str, dest: &str) -> Result<String, FsError> {
|
||||
} else {
|
||||
// Otherwise copy file to the specified destination
|
||||
fs::copy(src_path, dest_path).map_err(FsError::CopyFailed)?;
|
||||
if make_executable {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
if let Err(e) = set_executable(dest_path) {
|
||||
println!(
|
||||
"Warning: Failed to make {} executable: {}",
|
||||
dest_path.display(),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(format!("Successfully copied file '{}' to '{}'", src, dest))
|
||||
}
|
||||
} else if src_path.is_dir() {
|
||||
@ -269,6 +282,43 @@ pub fn copy(src: &str, dest: &str) -> Result<String, FsError> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively copy a file or directory from source to destination.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * `src` - The source path, which can include wildcards
|
||||
* * `dest` - The destination path
|
||||
*
|
||||
* # Returns
|
||||
*
|
||||
* * `Ok(String)` - A success message indicating what was copied
|
||||
* * `Err(FsError)` - An error if the copy operation failed
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```no_run
|
||||
* use sal::os::copy;
|
||||
*
|
||||
* fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
* // Copy a single file
|
||||
* let result = copy("file.txt", "backup/file.txt")?;
|
||||
*
|
||||
* // Copy multiple files using wildcards
|
||||
* let result = copy("*.txt", "backup/")?;
|
||||
*
|
||||
* // Copy a directory recursively
|
||||
* let result = copy("src_dir", "dest_dir")?;
|
||||
*
|
||||
* Ok(())
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
pub fn copy(src: &str, dest: &str) -> Result<String, FsError> {
|
||||
copy_internal(src, dest, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a binary to the correct location based on OS and user privileges.
|
||||
*
|
||||
@ -302,7 +352,7 @@ pub fn copy_bin(src: &str) -> Result<String, FsError> {
|
||||
.join("hero/bin")
|
||||
};
|
||||
|
||||
let result = copy(src, dest_path.to_str().unwrap());
|
||||
let result = copy_internal(src, dest_path.to_str().unwrap(), true);
|
||||
if let Ok(msg) = &result {
|
||||
println!("{}", msg);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user