Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// files that was distributed with this source code.

use crate::params::{parse_params, Format};
use crate::utils::report_failure_to_read_input_file;
use crate::utils::{exit_on_broken_pipe_or_panic, report_failure_to_read_input_file};
use crate::{context_diff, ed_diff, normal_diff, side_diff, unified_diff};
use std::env::ArgsOs;
use std::ffi::OsString;
Expand Down Expand Up @@ -90,8 +90,8 @@ pub fn main(opts: Peekable<ArgsOs>) -> ExitCode {
params.from.to_string_lossy(),
params.to.to_string_lossy()
);
} else {
io::stdout().write_all(&result).unwrap();
} else if let Err(e) = io::stdout().write_all(&result) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the println! for --brief just above will still panic on a closed pipe, no?

exit_on_broken_pipe_or_panic(e);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a test in tests/integration.rs (closed stdout pipe, and /dev/full)

}
if result.is_empty() {
maybe_report_identical_files();
Expand Down
17 changes: 14 additions & 3 deletions src/side_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{io::Write, vec};
use unicode_width::UnicodeWidthStr;

use crate::params::Params;
use crate::utils::exit_on_broken_pipe_or_panic;

const GUTTER_WIDTH_MIN: usize = 3;

Expand Down Expand Up @@ -350,10 +351,20 @@ pub fn diff<T: Write>(
*/
for result in diff::slice(&left_lines, &right_lines) {
match result {
Result::Left(left_ln) => push_output(left_ln, b"", b'<', output, &config).unwrap(),
Result::Right(right_ln) => push_output(b"", right_ln, b'>', output, &config).unwrap(),
Result::Left(left_ln) => {
if let Err(e) = push_output(left_ln, b"", b'<', output, &config) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

almost the same code 3 times.
could side_diff::diff return io::Result and let diff.rs handle it once?

exit_on_broken_pipe_or_panic(e);
}
}
Result::Right(right_ln) => {
if let Err(e) = push_output(b"", right_ln, b'>', output, &config) {
exit_on_broken_pipe_or_panic(e);
}
}
Result::Both(left_ln, right_ln) => {
push_output(left_ln, right_ln, b' ', output, &config).unwrap()
if let Err(e) = push_output(left_ln, right_ln, b' ', output, &config) {
exit_on_broken_pipe_or_panic(e);
}
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ use regex::Regex;
use std::{ffi::OsString, io::Write};
use unicode_width::UnicodeWidthStr;

/// Handle a write error to stdout: if the pipe was closed by the reader
/// (e.g. `diff big1 big2 | head`), exit quietly like GNU does under
/// `SIGPIPE` (128 + 13 = 141) instead of panicking with a core dump.
/// Any other write error is a genuine bug, so it still panics.
pub fn exit_on_broken_pipe_or_panic(e: std::io::Error) -> ! {
if e.kind() == std::io::ErrorKind::BrokenPipe {
std::process::exit(141);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't want process::exit in the lib, diff should stay embeddable.
could you please propagate the error and return ExitCode::from(141) from diff::main instead?

}
panic!("{e}");
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for panic

other write errors aren't bugs, e.g. diff a b > /dev/full.
GNU prints "write error" and exits 2, please do the same instead of panicking


/// Replace tabs by spaces in the input line.
/// Correctly handle multi-bytes characters.
/// This assumes that line does not contain any line breaks (if it does, the result is undefined).
Expand Down
Loading