Repository: knope-dev/knope (rust)
Issue: In dry runs, don't mention deleting a change file twice
Pull request description: fix: `--dry-run` will no longer report deleting the same changeset twice
Closes #635

Patch:
diff --git a/docs/src/content/docs/tutorials/releasing-multiple-packages.mdx b/docs/src/content/docs/tutorials/releasing-multiple-packages.mdx
index eabebc3..9b78e2b 100644
--- a/docs/src/content/docs/tutorials/releasing-multiple-packages.mdx
+++ b/docs/src/content/docs/tutorials/releasing-multiple-packages.mdx
@@ -280,7 +280,6 @@ knope release --dry-run
 
 ```text
 Would delete: .changeset/the_cheese_is_now_distributed_more_evenly.md
-Would delete: .changeset/the_cheese_is_now_distributed_more_evenly.md
 Would add the following to pizza/Cargo.toml: 3.14.16
 Would add the following to pizza/CHANGELOG.md:
 ## 3.14.16 (2023-11-11)
diff --git a/src/step/releases/changesets.rs b/src/step/releases/changesets.rs
index ea9fa03..38d192c 100644
--- a/src/step/releases/changesets.rs
+++ b/src/step/releases/changesets.rs
@@ -1,4 +1,4 @@
-use std::{fmt, io::Write, path::PathBuf};
+use std::{collections::HashSet, fmt, io::Write, path::PathBuf};
 
 use changesets::{ChangeSet, UniqueId, Versioning};
 use inquire::{MultiSelect, Select};
@@ -138,6 +138,7 @@ pub(crate) fn add_releases_from_changeset(
         return Ok(packages);
     }
     let mut changeset = ChangeSet::from_directory(&changeset_path)?;
+    let mut changesets_deleted = HashSet::new();
     Ok(packages
         .into_iter()
         .map(|mut package| {
@@ -150,21 +151,19 @@ pub(crate) fn add_releases_from_changeset(
                 package
                     .pending_changes
                     .extend(release_changes.changes.into_iter().map(|change| {
-                        if let Some(dry_run) = dry_run {
-                            writeln!(
-                                dry_run,
-                                "Would delete: {}",
-                                changeset_path
-                                    .join(change.unique_id.to_file_name())
-                                    .display()
-                            )
-                            .ok(); // Truly not the end of the world if stdio fails, and error handling is hard
-                        } else {
-                            // Error is ignored because we will attempt to double-delete some files.
-                            std::fs::remove_file(
-                                changeset_path.join(change.unique_id.to_file_name()),
-                            )
-                            .ok();
+                        let file_name = change.unique_id.to_file_name();
+                        if !changesets_deleted.contains(&file_name) {
+                            if let Some(dry_run) = dry_run {
+                                writeln!(
+                                    dry_run,
+                                    "Would delete: {}",
+                                    changeset_path.join(&file_name).display()
+                                )
+                                .ok(); // Truly not the end of the world if stdio fails, and error handling is hard
+                            } else {
+                                std::fs::remove_file(changeset_path.join(&file_name)).ok();
+                            }
+                            changesets_deleted.insert(file_name);
                         }
                         Change::ChangeSet(change)
                     }));


Test patch:
diff --git a/tests/prepare_release/verbose/dry_run_output.txt b/tests/prepare_release/verbose/dry_run_output.txt
index 72fe7c9..a071c99 100644
--- a/tests/prepare_release/verbose/dry_run_output.txt
+++ b/tests/prepare_release/verbose/dry_run_output.txt
@@ -5,7 +5,6 @@ Getting conventional commits since last release of package second
 Finding all commits since tag second/v0.4.6
 Would delete: .changeset/breaking_change.md
 Would delete: .changeset/feature.md
-Would delete: .changeset/feature.md
 Determining new version for first
 Looking for Git tags matching package name.
 Finding version for Cargo.toml