diff options
author | Thomas Otto <th1000s@posteo.net> | 2022-02-24 02:31:47 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-23 20:31:47 -0500 |
commit | f165f56b849f6a4cbb97f3ce2da585bd8b0b03d8 (patch) | |
tree | be7761093ee7878a4697e646058139a5098ca131 | |
parent | 9572adb744f460ba54fdcdd04d34d951b7b2f205 (diff) |
Fall back to plain diff when process substitution is used (#978)
When detecting input generated by `delta <(echo foo) <(echo bar)`
fall back to plain `diff` instead of `git diff --no-index`.
This does not respect various git settings anymore (the original reason
to switch from `diff` to `git diff`), but is better than just showing
the names of the temporary files.
-rw-r--r-- | src/subcommands/diff.rs | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/src/subcommands/diff.rs b/src/subcommands/diff.rs index f9cdd703..0cd7b5d3 100644 --- a/src/subcommands/diff.rs +++ b/src/subcommands/diff.rs @@ -1,5 +1,5 @@ use std::io::{ErrorKind, Write}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process; use bytelines::ByteLinesReader; @@ -27,23 +27,36 @@ You can also use delta to diff two files: `delta file_A file_B`." let minus_file = minus_file.unwrap(); let plus_file = plus_file.unwrap(); - let diff_command = "git"; - let diff_command_path = match grep_cli::resolve_binary(PathBuf::from(diff_command)) { + // When called as `delta <(echo foo) <(echo bar)`, then git as of version 2.34 just prints the + // diff of the filenames which were created by the process substitution and does not read their + // content, so fall back to plain `diff` which simply opens the given input as files. + // This fallback ignores git settings, but is better than nothing. + let via_process_substitution = + |f: &Path| f.starts_with("/proc/self/fd/") || f.starts_with("/dev/fd/"); + + let diff_cmd = if via_process_substitution(minus_file) || via_process_substitution(plus_file) { + ["diff", "-u", "--"].as_slice() + } else { + ["git", "diff", "--no-index", "--color", "--"].as_slice() + }; + + let diff_bin = diff_cmd[0]; + let diff_path = match grep_cli::resolve_binary(PathBuf::from(diff_bin)) { Ok(path) => path, Err(err) => { - eprintln!("Failed to resolve command '{}': {}", diff_command, err); + eprintln!("Failed to resolve command '{}': {}", diff_bin, err); return config.error_exit_code; } }; - let diff_process = process::Command::new(diff_command_path) - .args(&["diff", "--no-index", "--color"]) + let diff_process = process::Command::new(diff_path) + .args(&diff_cmd[1..]) .args(&[minus_file, plus_file]) .stdout(process::Stdio::piped()) .spawn(); if let Err(err) = diff_process { - eprintln!("Failed to execute the command '{}': {}", diff_command, err); + eprintln!("Failed to execute the command '{}': {}", diff_bin, err); return config.error_exit_code; } let mut diff_process = diff_process.unwrap(); @@ -62,17 +75,17 @@ You can also use delta to diff two files: `delta file_A file_B`." } }; - // Return the exit code from the `git diff` processl, so that the exit code + // Return the exit code from the diff process, so that the exit code // contract of `delta file_A file_B` is the same as that of `diff file_A // file_B` (i.e. 0 if same, 1 if different, 2 if error). diff_process .wait() .unwrap_or_else(|_| { - delta_unreachable(&format!("'{}' process not running.", diff_command)); + delta_unreachable(&format!("'{}' process not running.", diff_bin)); }) .code() .unwrap_or_else(|| { - eprintln!("'{}' process terminated without exit status.", diff_command); + eprintln!("'{}' process terminated without exit status.", diff_bin); config.error_exit_code }) } |