diff --git a/NEWS.md b/NEWS.md index 1c90563d..05b670ba 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,9 @@ # cargo-mutants changelog +## Unreleased + +- Fixed: Fixed spurious "Patch input contains repeated filenames" error when `--in-diff` is given a patch that deletes multiple files. + ## 23.12.2 - New: A `--shard k/n` allows you to split the work across n independent parallel `cargo mutants` invocations running on separate machines to get a faster overall solution on large suites. You, or your CI system, are responsible for launching all the shards and checking whether any of them failed. diff --git a/src/in_diff.rs b/src/in_diff.rs index f57e9f5a..480642bc 100644 --- a/src/in_diff.rs +++ b/src/in_diff.rs @@ -25,6 +25,10 @@ pub fn diff_filter(mutants: Vec, diff_text: &str) -> Result> let mut lines_changed_by_path: HashMap<&Utf8Path, Vec> = HashMap::new(); for patch in &patches { let path = strip_patch_path(&patch.new.path); + if path == "/dev/null" { + // The file was deleted; we can't possibly match anything in it. + continue; + } if lines_changed_by_path .insert(path, affected_lines(patch)) .is_some() diff --git a/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap b/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap index fdf51028..4db3dc38 100644 --- a/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap +++ b/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap @@ -181,6 +181,7 @@ src/fnvalue.rs: replace == with != in match_first_type_arg src/in_diff.rs: replace diff_filter -> Result> with Ok(vec![]) src/in_diff.rs: replace diff_filter -> Result> with Ok(vec![Default::default()]) src/in_diff.rs: replace diff_filter -> Result> with Err(::anyhow::anyhow!("mutated!")) +src/in_diff.rs: replace == with != in diff_filter src/in_diff.rs: replace check_diff_new_text_matches -> Result<()> with Ok(()) src/in_diff.rs: replace check_diff_new_text_matches -> Result<()> with Err(::anyhow::anyhow!("mutated!")) src/in_diff.rs: replace != with == in check_diff_new_text_matches diff --git a/tests/cli/in_diff.rs b/tests/cli/in_diff.rs index 51e8f9b0..95c92e79 100644 --- a/tests/cli/in_diff.rs +++ b/tests/cli/in_diff.rs @@ -96,3 +96,42 @@ fn mismatched_diff_causes_error() { "Diff content doesn't match source file: src/lib.rs", )); } + +/// If the diff contains multiple deletions (with a new filename of /dev/null), +/// don't fail. +/// +/// +#[test] +fn diff_with_multiple_deletions_is_ok() { + let diff = indoc! {r#" + diff --git a/src/monitor/collect.rs b/src/monitor/collect.rs + deleted file mode 100644 + index d842cf9..0000000 + --- a/src/monitor/collect.rs + +++ /dev/null + @@ -1,1 +0,0 @@ + -// Some stuff + diff --git a/src/monitor/another.rs b/src/monitor/another.rs + deleted file mode 100644 + index d842cf9..0000000 + --- a/src/monitor/collect.rs + +++ /dev/null + @@ -1,1 +0,0 @@ + -// More stuff + "#}; + let mut diff_file = NamedTempFile::new().unwrap(); + diff_file.write_all(diff.as_bytes()).unwrap(); + + let tmp = copy_of_testdata("diff1"); + + run() + .args(["mutants", "--no-shuffle", "-d"]) + .arg(tmp.path()) + .arg("--in-diff") + .arg(diff_file.path()) + .assert() + .stderr(predicates::str::contains( + "No mutants found under the active filters", + )) + .success(); +}