use std::io::{Read, Write};
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use std::path::PathBuf;
use std::{env, fs};
use crate::errors::{ConfGuardError, ConfGuardResult};
use crate::util::RESOURCES_DIR;
use tracing::debug;
pub mod path;
pub mod testing;
pub fn file_contents(path: &Path) -> ConfGuardResult<String> {
let mut file = fs::File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
pub fn copy_file_from_resources(
file_name: &str,
destination: &str,
executable: bool,
) -> ConfGuardResult<()> {
let file = RESOURCES_DIR
.get_file(file_name)
.ok_or_else(|| ConfGuardError::ResourceNotFound(file_name.to_string()))?;
debug!("{:?} {:?}", RESOURCES_DIR, file);
let destination_file = Path::new(destination);
if let Some(parent) = destination_file.parent() {
if !parent.exists() {
fs::create_dir_all(parent)?;
}
}
let mut file_writer = fs::File::create(destination_file)?;
file_writer.write_all(file.contents())?;
if executable {
let mut permissions = file_writer.metadata()?.permissions();
permissions.set_mode(0o755);
fs::set_permissions(destination_file, permissions)?;
}
Ok(())
}
pub fn assert_path_does_not_include(path: &Path, forbidden: &[&str]) {
let path_str = path
.to_str()
.expect("test paths are valid UTF-8 on supported platforms");
for forbidden_item in forbidden {
assert!(
!path_str.contains(forbidden_item),
"The path '{}' contains a forbidden string or subpath: '{}'",
path_str,
forbidden_item
);
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::read_to_string;
use tempfile::tempdir;
#[test]
fn test_assert_path_does_not_include() {
let valid_path = Path::new("/home/user/projects/rust_project");
let invalid_path = Path::new("/home/user/projects/secret_project");
let forbidden = ["secret", "private"];
assert_path_does_not_include(valid_path, &forbidden);
let result = std::panic::catch_unwind(|| {
assert_path_does_not_include(invalid_path, &forbidden);
});
assert!(result.is_err());
}
#[test]
fn test_copy_file_from_resources() {
let dir = tempdir().unwrap();
let dest_path = dir.path().join("test_file.txt");
let result = copy_file_from_resources(
"asset_to_be_included.txt",
dest_path.to_str().unwrap(),
true,
);
assert!(result.is_ok());
assert!(dest_path.exists());
let contents = read_to_string(&dest_path).unwrap();
assert_eq!(contents, "Hello, World!\n");
let metadata = dest_path.metadata().unwrap();
let permissions = metadata.permissions();
assert_eq!(
permissions.mode() & 0o100,
0o100,
"File should be executable"
);
}
#[test]
fn test_copy_file_from_resources2() {
let dir = tempdir().unwrap();
let dest_path = dir.path().join(".envrc");
let result = copy_file_from_resources("dot.envrc", dest_path.to_str().unwrap(), false);
assert!(result.is_ok());
assert!(dest_path.exists());
let _ = read_to_string(&dest_path).unwrap();
}
}