From ddff2b9c2cf8845b5e2d77fd86d143626f976aa9 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Fri, 8 Mar 2024 13:13:59 -0500 Subject: [PATCH] Make sure that the merged documents don't have duplicate contents --- cmd/soroban-cli/src/commands/contract/init.rs | 77 ++++++++++++++++++- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/init.rs b/cmd/soroban-cli/src/commands/contract/init.rs index b45c6fd921..70b69f0056 100644 --- a/cmd/soroban-cli/src/commands/contract/init.rs +++ b/cmd/soroban-cli/src/commands/contract/init.rs @@ -433,19 +433,41 @@ fn check_internet_connection() -> bool { false } +// Appends the contents of a file to another file, separated by a delimiter fn append_contents(from: &Path, to: &Path) -> Result<(), Error> { let mut from_file = File::open(from)?; let mut from_content = String::new(); from_file.read_to_string(&mut from_content)?; - let mut to_file = OpenOptions::new().append(true).open(to)?; - to_file.write_all("\n\n".as_bytes())?; + let mut to_file = OpenOptions::new().read(true).append(true).open(to)?; + let mut to_content = String::new(); + to_file.read_to_string(&mut to_content)?; + + let delimiter = get_merged_file_delimiter(to)?; + // if the to file already contains the delimiter, we don't need to append the contents again + if to_content.contains(&delimiter) { + return Ok(()); + } + + to_file.write_all(delimiter.as_bytes())?; to_file.write_all(from_content.as_bytes())?; println!("ℹ️ Merging {} contents", &to.to_string_lossy()); Ok(()) } +fn get_merged_file_delimiter(file_path: &Path) -> Result { + let comment = if file_path.to_string_lossy().contains("README.md") { + "[//]: # \"The following is the Frontend Template's README.md\"".to_string() + } else if file_path.to_string_lossy().contains("gitignore") { + "# The following is from the Frontend Template's .gitignore".to_string() + } else { + "".to_string() + }; + + Ok(format!("\n\n---\n\n{comment}\n\n").to_string()) +} + #[cfg(test)] mod tests { use std::fs::read_to_string; @@ -553,7 +575,43 @@ mod tests { assert_astro_files_exist(&project_dir); assert_gitignore_includes_astro_paths(&project_dir); assert_package_json_files_have_correct_name(&project_dir); - assert_readme_includes_frontend_file_appended(&project_dir); + assert_readme_includes_frontend_readme_appended(&project_dir); + + temp_dir.close().unwrap(); + } + + #[test] + fn test_init_does_not_duplicate_frontend_readme_contents_when_run_more_than_once() { + let temp_dir = tempfile::tempdir().unwrap(); + let project_dir = temp_dir.path().join(TEST_PROJECT_NAME); + let with_examples = vec![]; + init( + project_dir.as_path(), + &"https://github.com/AhaLabs/soroban-astro-template".to_string(), + &with_examples, + ) + .unwrap(); + + // call init again to make sure the README.md's contents are not duplicated + init( + project_dir.as_path(), + &"https://github.com/AhaLabs/soroban-astro-template".to_string(), + &with_examples, + ) + .unwrap(); + + assert_base_template_files_exist(&project_dir); + assert_default_hello_world_contract_files_exist(&project_dir); + assert_base_excluded_paths_do_not_exist(&project_dir); + + // check that the contract's Cargo.toml file uses the workspace for dependencies + assert_contract_cargo_file_uses_workspace(&project_dir, "hello_world"); + assert_base_excluded_paths_do_not_exist(&project_dir); + + assert_astro_files_exist(&project_dir); + assert_gitignore_includes_astro_paths(&project_dir); + assert_package_json_files_have_correct_name(&project_dir); + assert_readme_includes_frontend_readme_appended(&project_dir); temp_dir.close().unwrap(); } @@ -629,9 +687,20 @@ mod tests { assert!(package_lock_json_str.contains(&format!("\"name\":\"{TEST_PROJECT_NAME}\""))); } - fn assert_readme_includes_frontend_file_appended(project_dir: &Path) { + fn assert_readme_includes_frontend_readme_appended(project_dir: &Path) { let readme_path = project_dir.join("README.md"); let readme_str = read_to_string(readme_path).unwrap(); assert!(readme_str.contains("Soroban Frontend in Astro")); + let expected = "[//]: # \"The following is the Frontend Template's README.md\""; + assert!(readme_str.contains(expected)); + + let readme_path = project_dir.join("README.md"); + let readme_str = read_to_string(readme_path).unwrap(); + println!("readme_str: {}", readme_str); + let readme_frontend_merge_delimiter = + "[//]: # \"The following is the Frontend Template's README.md\""; + let count = readme_str.matches(readme_frontend_merge_delimiter).count(); + // making sure it is in there just once so that it isn't duplicated if `contract init` is run again + assert!(count == 1); } }