diff --git a/Cargo.lock b/Cargo.lock index cf8f04f..92ad218 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,6 +81,7 @@ dependencies = [ "diff", "predicates", "pretty_assertions", + "same-file", "tempfile", ] @@ -248,6 +249,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" version = "1.0.197" @@ -312,6 +322,37 @@ dependencies = [ "libc", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index f1c7b71..3804a81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ path = "src/main.rs" [dependencies] diff = "0.1.10" +same-file = "1.0.6" [dev-dependencies] pretty_assertions = "1" diff --git a/src/main.rs b/src/main.rs index a684ff4..ef14096 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,10 +28,25 @@ fn main() -> ExitCode { to, context_count, format, + report_identical_files, } = parse_params(opts).unwrap_or_else(|error| { eprintln!("{error}"); exit(2); }); + // if from and to are the same file, no need to perform any comparison + let maybe_report_identical_files = || { + if report_identical_files { + println!( + "Files {} and {} are identical", + from.to_string_lossy(), + to.to_string_lossy(), + ) + } + }; + if same_file::is_same_file(&from, &to).unwrap_or(false) { + maybe_report_identical_files(); + return ExitCode::SUCCESS; + } // read files let from_content = match fs::read(&from) { Ok(from_content) => from_content, @@ -71,6 +86,7 @@ fn main() -> ExitCode { }; io::stdout().write_all(&result).unwrap(); if result.is_empty() { + maybe_report_identical_files(); ExitCode::SUCCESS } else { ExitCode::from(1) diff --git a/src/params.rs b/src/params.rs index b118be7..66d3d56 100644 --- a/src/params.rs +++ b/src/params.rs @@ -25,6 +25,7 @@ pub struct Params { pub to: OsString, pub format: Format, pub context_count: usize, + pub report_identical_files: bool, } pub fn parse_params>(opts: I) -> Result { @@ -38,6 +39,7 @@ pub fn parse_params>(opts: I) -> Result>(opts: I) -> Result>(opts: I) -> Result Result<(), Box> { Ok(()) } +#[test] +fn no_differences_report_identical_files() -> Result<(), Box> { + // same file + let mut file1 = NamedTempFile::new()?; + file1.write_all("foo\n".as_bytes())?; + for option in ["", "-u", "-c", "-e"] { + let mut cmd = Command::cargo_bin("diffutils")?; + if !option.is_empty() { + cmd.arg(option); + } + cmd.arg("-s").arg(file1.path()).arg(file1.path()); + cmd.assert() + .code(predicate::eq(0)) + .success() + .stdout(predicate::eq(format!( + "Files {} and {} are identical\n", + file1.path().to_string_lossy(), + file1.path().to_string_lossy(), + ))); + } + // two files with the same content + let mut file2 = NamedTempFile::new()?; + file2.write_all("foo\n".as_bytes())?; + for option in ["", "-u", "-c", "-e"] { + let mut cmd = Command::cargo_bin("diffutils")?; + if !option.is_empty() { + cmd.arg(option); + } + cmd.arg("-s").arg(file1.path()).arg(file2.path()); + cmd.assert() + .code(predicate::eq(0)) + .success() + .stdout(predicate::eq(format!( + "Files {} and {} are identical\n", + file1.path().to_string_lossy(), + file2.path().to_string_lossy(), + ))); + } + Ok(()) +} + #[test] fn differences() -> Result<(), Box> { let mut file1 = NamedTempFile::new()?;