diff --git a/src/diff.rs b/src/diff.rs index f4c0614..47deb30 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -70,6 +70,9 @@ pub fn main(opts: Peekable) -> ExitCode { return ExitCode::from(2); } + // Side-by-side writes its output directly, so its result cannot indicate differences. + let side_by_side_differs = params.format == Format::SideBySide && from_content != to_content; + // run diff let result: Vec = match params.format { Format::Normal => normal_diff::diff(&from_content, &to_content, ¶ms), @@ -79,12 +82,14 @@ pub fn main(opts: Peekable) -> ExitCode { eprintln!("{error}"); exit(2); }), + Format::SideBySide if params.brief => Vec::new(), Format::SideBySide => { let mut output = stdout().lock(); side_diff::diff(&from_content, &to_content, &mut output, ¶ms) } }; - if params.brief && !result.is_empty() { + let differs = side_by_side_differs || !result.is_empty(); + if params.brief && differs { println!( "Files {} and {} differ", params.from.to_string_lossy(), @@ -93,7 +98,7 @@ pub fn main(opts: Peekable) -> ExitCode { } else { io::stdout().write_all(&result).unwrap(); } - if result.is_empty() { + if !differs { maybe_report_identical_files(); ExitCode::SUCCESS } else { diff --git a/tests/integration.rs b/tests/integration.rs index 12aabb8..8362e05 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -119,6 +119,76 @@ mod diff { Ok(()) } + #[test] + fn side_by_side_exit_status() -> Result<(), Box> { + let dir = tempdir()?; + let left = dir.path().join("left"); + let right = dir.path().join("right"); + + for (left_content, right_content, code) in [ + (b"alpha\n".as_slice(), b"alpha\n".as_slice(), 0), + (b"alpha\n", b"alpha\nbeta\n", 1), + (b"alpha\n", b"bravo\n", 1), + (b"alpha", b"alpha\n", 1), + (b"alpha", b"alpha", 0), + (b"\xff\n", b"\xfe\n", 1), + (b"", b"alpha\n", 1), + (b"alpha\n", b"", 1), + (b"", b"", 0), + ] { + std::fs::write(&left, left_content)?; + std::fs::write(&right, right_content)?; + for options in [ + &["-y"][..], + &["-y", "-q"], + &["-y", "-s"], + &["-y", "--width=40"], + ] { + let mut cmd = cargo_bin_cmd!("diffutils"); + cmd.arg("diff").args(options).arg(&left).arg(&right); + let assertion = cmd + .assert() + .code(predicate::eq(code)) + .stderr(predicate::str::is_empty()); + if options == ["-y", "-q"] { + let expected = if code == 1 { + format!("Files {} and {} differ\n", left.display(), right.display()) + } else { + String::new() + }; + assertion.stdout(predicate::eq(expected)); + } + } + } + + std::fs::write(&left, b"alpha\n")?; + for (right_content, identical) in [(b"alpha\n".as_slice(), true), (b"bravo\n", false)] { + std::fs::write(&right, right_content)?; + let mut cmd = cargo_bin_cmd!("diffutils"); + cmd.arg("diff").arg("-y").arg("-s").arg(&left).arg(&right); + let assertion = cmd.assert(); + if identical { + assertion.stdout(predicate::str::contains(format!( + "Files {} and {} are identical\n", + left.display(), + right.display() + ))); + } else { + assertion.stdout(predicate::str::contains("are identical").not()); + } + } + + std::fs::remove_file(&right)?; + let mut cmd = cargo_bin_cmd!("diffutils"); + cmd.arg("diff").arg("-y").arg(&left).arg(&right); + cmd.assert() + .code(predicate::eq(2)) + .failure() + .stdout(predicate::str::is_empty()) + .stderr(predicate::str::contains("right")); + Ok(()) + } + #[test] fn no_differences_report_identical_files() -> Result<(), Box> { // same file