From 6be94d8683fea64d50eecb92c81e485c35033794 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 22:31:44 +0000 Subject: [PATCH 1/5] chore(deps): update rust crate tempfile to 3.10.1 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43bbdbf..69c69d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -293,9 +293,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", diff --git a/Cargo.toml b/Cargo.toml index b512a7b..6de6dcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ unicode-width = "0.1.11" pretty_assertions = "1" assert_cmd = "2.0.14" predicates = "3.1.0" -tempfile = "3.10.0" +tempfile = "3.10.1" # The profile that 'cargo dist' will build with [profile.dist] From c325291696b10de5a8fde65b5322d40163e2f74d Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Fri, 5 Apr 2024 23:22:26 +0200 Subject: [PATCH 2/5] Unit test to verify that conflicting output styles result in an error --- src/params.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/params.rs b/src/params.rs index 74e8d15..18f8949 100644 --- a/src/params.rs +++ b/src/params.rs @@ -502,4 +502,15 @@ mod tests { fn empty() { assert!(parse_params([].iter().cloned()).is_err()); } + #[test] + fn conflicting_output_styles() { + for (arg1, arg2) in [("-u", "-c"), ("-u", "-e"), ("-c", "-u"), ("-c", "-U42")] { + assert!(parse_params( + [os("diff"), os(arg1), os(arg2), os("foo"), os("bar")] + .iter() + .cloned() + ) + .is_err()); + } + } } From 6dc34fed44ea7bd8f87de41b40785f9cd6486cba Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Wed, 3 Apr 2024 22:18:12 +0200 Subject: [PATCH 3/5] Handle the rewrite of "-" to "/dev/stdin" in main to leave the filenames unchanged (fixes #46) --- src/main.rs | 14 ++++++++++---- src/params.rs | 12 ++++++------ tests/integration.rs | 27 ++++++++++++++++----------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/main.rs b/src/main.rs index a19e646..de4bbbb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use crate::params::{parse_params, Format}; use std::env; - +use std::ffi::OsString; use std::fs; use std::io::{self, Write}; use std::process::{exit, ExitCode}; @@ -38,19 +38,25 @@ fn main() -> ExitCode { ); } }; - if same_file::is_same_file(¶ms.from, ¶ms.to).unwrap_or(false) { + if params.from == "-" && params.to == "-" + || same_file::is_same_file(¶ms.from, ¶ms.to).unwrap_or(false) + { maybe_report_identical_files(); return ExitCode::SUCCESS; } // read files - let from_content = match fs::read(¶ms.from) { + fn read_file_contents(filepath: &OsString) -> io::Result> { + let stdin = OsString::from("/dev/stdin"); + fs::read(if filepath == "-" { &stdin } else { filepath }) + } + let from_content = match read_file_contents(¶ms.from) { Ok(from_content) => from_content, Err(e) => { eprintln!("Failed to read from-file: {e}"); return ExitCode::from(2); } }; - let to_content = match fs::read(¶ms.to) { + let to_content = match read_file_contents(¶ms.to) { Ok(to_content) => to_content, Err(e) => { eprintln!("Failed to read to-file: {e}"); diff --git a/src/params.rs b/src/params.rs index 18f8949..7e9cc78 100644 --- a/src/params.rs +++ b/src/params.rs @@ -67,9 +67,9 @@ pub fn parse_params>(opts: I) -> Result ", exe.to_string_lossy())); } @@ -461,14 +461,14 @@ mod tests { assert_eq!( Ok(Params { from: os("foo"), - to: os("/dev/stdin"), + to: os("-"), ..Default::default() }), parse_params([os("diff"), os("foo"), os("-")].iter().cloned()) ); assert_eq!( Ok(Params { - from: os("/dev/stdin"), + from: os("-"), to: os("bar"), ..Default::default() }), @@ -476,8 +476,8 @@ mod tests { ); assert_eq!( Ok(Params { - from: os("/dev/stdin"), - to: os("/dev/stdin"), + from: os("-"), + to: os("-"), ..Default::default() }), parse_params([os("diff"), os("-"), os("-")].iter().cloned()) diff --git a/tests/integration.rs b/tests/integration.rs index 5ad624e..240d60b 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -22,25 +22,30 @@ fn unknown_param() -> Result<(), Box> { } #[test] -fn cannot_read_from_file() -> Result<(), Box> { +fn cannot_read_files() -> Result<(), Box> { + let file = NamedTempFile::new()?; + let mut cmd = Command::cargo_bin("diffutils")?; - cmd.arg("foo.txt").arg("bar.txt"); + cmd.arg("foo.txt").arg(file.path()); cmd.assert() .code(predicate::eq(2)) .failure() .stderr(predicate::str::starts_with("Failed to read from-file")); - Ok(()) -} -#[test] -fn cannot_read_to_file() -> Result<(), Box> { - let file = NamedTempFile::new()?; let mut cmd = Command::cargo_bin("diffutils")?; - cmd.arg(file.path()).arg("bar.txt"); + cmd.arg(file.path()).arg("foo.txt"); cmd.assert() .code(predicate::eq(2)) .failure() .stderr(predicate::str::starts_with("Failed to read to-file")); + + let mut cmd = Command::cargo_bin("diffutils")?; + cmd.arg("foo.txt").arg("foo.txt"); + cmd.assert() + .code(predicate::eq(2)) + .failure() + .stderr(predicate::str::starts_with("Failed to read from-file")); + Ok(()) } @@ -177,7 +182,7 @@ fn read_from_stdin() -> Result<(), Box> { .code(predicate::eq(1)) .failure() .stdout(predicate::eq(format!( - "--- {}\t\n+++ /dev/stdin\t\n@@ -1 +1 @@\n-foo\n+bar\n", + "--- {}\t\n+++ -\t\n@@ -1 +1 @@\n-foo\n+bar\n", file1.path().to_string_lossy() ))); @@ -190,12 +195,12 @@ fn read_from_stdin() -> Result<(), Box> { .code(predicate::eq(1)) .failure() .stdout(predicate::eq(format!( - "--- /dev/stdin\t\n+++ {}\t\n@@ -1 +1 @@\n-foo\n+bar\n", + "--- -\t\n+++ {}\t\n@@ -1 +1 @@\n-foo\n+bar\n", file2.path().to_string_lossy() ))); let mut cmd = Command::cargo_bin("diffutils")?; - cmd.arg("-u").arg("-").arg("-").write_stdin("foo\n"); + cmd.arg("-u").arg("-").arg("-"); cmd.assert() .code(predicate::eq(0)) .success() From 84ad116845db263cfb04234fb509011f59cbb8f1 Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Thu, 4 Apr 2024 22:14:03 +0200 Subject: [PATCH 4/5] Use io::stdin() to read from standard input in a portable manner --- src/main.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index de4bbbb..6858f5e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use crate::params::{parse_params, Format}; use std::env; use std::ffi::OsString; use std::fs; -use std::io::{self, Write}; +use std::io::{self, Read, Write}; use std::process::{exit, ExitCode}; mod context_diff; @@ -46,8 +46,12 @@ fn main() -> ExitCode { } // read files fn read_file_contents(filepath: &OsString) -> io::Result> { - let stdin = OsString::from("/dev/stdin"); - fs::read(if filepath == "-" { &stdin } else { filepath }) + if filepath == "-" { + let mut content = Vec::new(); + io::stdin().read_to_end(&mut content).and(Ok(content)) + } else { + fs::read(filepath) + } } let from_content = match read_file_contents(¶ms.from) { Ok(from_content) => from_content, From e1c319f96b371bf80864399490a39a74ecef2e6b Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Mon, 8 Apr 2024 22:36:14 +0200 Subject: [PATCH 5/5] Add an integration test for reading from "/dev/stdin" on unix-like systems --- tests/integration.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/integration.rs b/tests/integration.rs index 240d60b..8c0491a 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -206,5 +206,21 @@ fn read_from_stdin() -> Result<(), Box> { .success() .stdout(predicate::str::is_empty()); + #[cfg(unix)] + { + let mut cmd = Command::cargo_bin("diffutils")?; + cmd.arg("-u") + .arg(file1.path()) + .arg("/dev/stdin") + .write_stdin("bar\n"); + cmd.assert() + .code(predicate::eq(1)) + .failure() + .stdout(predicate::eq(format!( + "--- {}\t\n+++ /dev/stdin\t\n@@ -1 +1 @@\n-foo\n+bar\n", + file1.path().to_string_lossy() + ))); + } + Ok(()) }