use crate::load::load_file_as_string;
use crate::save::save_string_to_file;
use std::panic;
use std::path::Path;
use walkdir::WalkDir;
pub fn replace_str_in_file<P: AsRef<Path>>(path: P, old_string: &str, new_string: &str) {
let content = load_file_as_string(&path);
if content.contains(old_string) {
let new_content = content.replace(old_string, new_string);
save_string_to_file(&new_content, path);
}
}
pub fn replace_str_in_files<P: AsRef<Path>>(path: P, old_string: &str, new_string: &str) {
for entry in WalkDir::new(path).into_iter().filter_map(Result::ok) {
let entry_path = entry.path();
if entry_path.is_file() {
let result =
panic::catch_unwind(|| replace_str_in_file(entry_path, old_string, new_string));
if result.is_err() {
eprintln!(
"Failed to replace string in file '{}'.",
entry_path.display(),
);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::get_temp_dir_path;
use std::path::PathBuf;
use tempfile::tempdir;
#[test]
fn test_replace_str_in_file() {
let temp_dir = tempdir().unwrap();
let temp_dir_path = get_temp_dir_path(&temp_dir);
let file_path: PathBuf = temp_dir_path.join("test_file.txt");
let file_paths: Vec<Box<dyn AsRef<Path>>> = vec![
Box::new(file_path.to_str().unwrap()), Box::new(file_path.to_str().unwrap().to_string()), Box::new(file_path.as_path()), Box::new(file_path.clone()), ];
for file_path in file_paths {
let file_path = file_path.as_ref();
save_string_to_file("Hello, world, hello, Hello!", file_path);
replace_str_in_file(file_path, "Hello", "Goodbye");
let content = load_file_as_string(file_path);
assert_eq!(content, "Goodbye, world, hello, Goodbye!");
}
}
#[test]
fn test_replace_str_in_files_basic() {
let temp_dir = tempdir().unwrap();
let temp_dir_path = get_temp_dir_path(&temp_dir);
let file_1_path = temp_dir_path.join("file_1.txt");
let file_2_path = temp_dir_path.join("file_2.txt");
let file_3_path = temp_dir_path.join("file_3.txt");
let file_1_paths: Vec<Box<dyn AsRef<Path>>> = vec![
Box::new(file_1_path.to_str().unwrap()), Box::new(file_1_path.to_str().unwrap().to_string()), Box::new(file_1_path.as_path()), Box::new(file_1_path.clone()), ];
let file_2_paths: Vec<Box<dyn AsRef<Path>>> = vec![
Box::new(file_2_path.to_str().unwrap()), Box::new(file_2_path.to_str().unwrap().to_string()), Box::new(file_2_path.as_path()), Box::new(file_2_path.clone()), ];
let file_3_paths: Vec<Box<dyn AsRef<Path>>> = vec![
Box::new(file_3_path.to_str().unwrap()), Box::new(file_3_path.to_str().unwrap().to_string()), Box::new(file_3_path.as_path()), Box::new(file_3_path.clone()), ];
let file_1_contents = "hello foo world";
let file_2_contents = "no foo here";
let file_3_contents = "nothing to replace";
for ((file_1_path, file_2_path), file_3_path) in
file_1_paths.into_iter().zip(file_2_paths).zip(file_3_paths)
{
let file_1_path = file_1_path.as_ref();
let file_2_path = file_2_path.as_ref();
let file_3_path = file_3_path.as_ref();
save_string_to_file(file_1_contents, file_1_path);
save_string_to_file(file_2_contents, file_2_path);
save_string_to_file(file_3_contents, file_3_path);
replace_str_in_files(&temp_dir_path, "foo", "bar");
let content1 = load_file_as_string(file_1_path);
assert_eq!(content1, "hello bar world");
let content2 = load_file_as_string(file_2_path);
assert_eq!(content2, "no bar here");
let content3 = load_file_as_string(file_3_path);
assert_eq!(content3, "nothing to replace");
}
}
#[test]
fn test_replace_str_in_files_nested() {
let temp_dir = tempdir().unwrap();
let temp_dir_path = get_temp_dir_path(&temp_dir);
let root_file_path = temp_dir_path.join("root.txt");
let nested_file_path = temp_dir_path.join("nested/nested.txt");
let root_file_paths: Vec<Box<dyn AsRef<Path>>> = vec![
Box::new(root_file_path.to_str().unwrap()), Box::new(root_file_path.to_str().unwrap().to_string()), Box::new(root_file_path.as_path()), Box::new(root_file_path.clone()), ];
let nested_file_paths: Vec<Box<dyn AsRef<Path>>> = vec![
Box::new(nested_file_path.to_str().unwrap()), Box::new(nested_file_path.to_str().unwrap().to_string()), Box::new(nested_file_path.as_path()), Box::new(nested_file_path.clone()), ];
for (root_file_path, nested_file_path) in root_file_paths.into_iter().zip(nested_file_paths)
{
let root_file_path = root_file_path.as_ref();
let nested_file_path = nested_file_path.as_ref();
save_string_to_file("replace me", root_file_path);
save_string_to_file("replace me too", nested_file_path);
replace_str_in_files(temp_dir.path(), "replace", "changed");
let root_content = load_file_as_string(root_file_path);
assert_eq!(root_content, "changed me");
let nested_content = load_file_as_string(nested_file_path);
assert_eq!(nested_content, "changed me too");
}
}
}