diff --git a/src/action/base/create_or_insert_into_file.rs b/src/action/base/create_or_insert_into_file.rs index b6ed559..94dd72d 100644 --- a/src/action/base/create_or_insert_into_file.rs +++ b/src/action/base/create_or_insert_into_file.rs @@ -244,7 +244,7 @@ impl Action for CreateOrInsertIntoFile { file_contents.replace_range(start..end, "") } - if buf.is_empty() { + if file_contents.is_empty() { remove_file(&path) .await .map_err(|e| ActionError::Remove(path.to_owned(), e))?; @@ -252,10 +252,79 @@ impl Action for CreateOrInsertIntoFile { file.seek(SeekFrom::Start(0)) .await .map_err(|e| ActionError::Seek(path.to_owned(), e))?; + file.set_len(0) + .await + .map_err(|e| ActionError::Truncate(path.to_owned(), e))?; file.write_all(file_contents.as_bytes()) .await .map_err(|e| ActionError::Write(path.to_owned(), e))?; + file.flush() + .await + .map_err(|e| ActionError::Flush(path.to_owned(), e))?; } Ok(()) } } + +#[cfg(test)] +mod test { + use super::*; + + #[tokio::test] + async fn creates_and_deletes_file() -> eyre::Result<()> { + let temp_dir = tempdir::TempDir::new("nix_installer_create_or_insert_into_file")?; + let test_file = temp_dir.path().join("creates_and_deletes_file"); + let mut action = CreateOrInsertIntoFile::plan( + test_file.clone(), + None, + None, + None, + "Test".into(), + Position::Beginning, + ) + .await?; + + action.try_execute().await?; + + action.try_revert().await?; + + assert!(!test_file.exists(), "File should have been deleted"); + + Ok(()) + } + + #[tokio::test] + async fn edits_and_reverts_file() -> eyre::Result<()> { + let temp_dir = tempdir::TempDir::new("nix_installer_create_or_insert_into_file")?; + let test_file = temp_dir.path().join("edits_and_reverts_file"); + + let test_content = "Some other content"; + tokio::fs::write(&test_file, test_content) + .await + .expect("Could not write to test temp file"); + + let mut action = CreateOrInsertIntoFile::plan( + test_file.clone(), + None, + None, + None, + "Test".into(), + Position::Beginning, + ) + .await?; + + action.try_execute().await?; + + action.try_revert().await?; + + assert!(test_file.exists(), "File should have not been deleted"); + + let read_content = tokio::fs::read_to_string(test_file) + .await + .expect("Could not read test temp file"); + + assert_eq!(test_content, read_content); + + Ok(()) + } +} diff --git a/src/action/mod.rs b/src/action/mod.rs index 5c2b39b..252ef2e 100644 --- a/src/action/mod.rs +++ b/src/action/mod.rs @@ -298,6 +298,10 @@ pub enum ActionError { Write(std::path::PathBuf, #[source] std::io::Error), #[error("Seek path `{0}`")] Seek(std::path::PathBuf, #[source] std::io::Error), + #[error("Flushing `{0}`")] + Flush(std::path::PathBuf, #[source] std::io::Error), + #[error("Truncating `{0}`")] + Truncate(std::path::PathBuf, #[source] std::io::Error), #[error("Getting uid for user `{0}`")] UserId(String, #[source] nix::errno::Errno), #[error("Getting user `{0}`")]