summaryrefslogtreecommitdiff
path: root/src/handlers
diff options
context:
space:
mode:
authorPaul <dominiak.pawel@gmail.com>2024-03-02 15:06:31 +0100
committerGitHub <noreply@github.com>2024-03-02 09:06:31 -0500
commit977f89ae0d8cd46bd8cab67a5fcc37b876abe31d (patch)
tree1e7f4e2130f224af67a0103971190e78c690366e /src/handlers
parentf7ae06a5f1e6943d4a78c8ede313ecd89c8563db (diff)
Fix headers of modified binary files, closes #1621 (#1629)
Diffstat (limited to 'src/handlers')
-rw-r--r--src/handlers/diff_header.rs2
-rw-r--r--src/handlers/diff_header_diff.rs14
-rw-r--r--src/handlers/diff_header_misc.rs33
3 files changed, 32 insertions, 17 deletions
diff --git a/src/handlers/diff_header.rs b/src/handlers/diff_header.rs
index 334ca76..3c71a61 100644
--- a/src/handlers/diff_header.rs
+++ b/src/handlers/diff_header.rs
@@ -357,7 +357,7 @@ fn parse_diff_header_line(line: &str, git_diff_name: bool) -> (String, FileEvent
/// Given input like "diff --git a/src/my file.rs b/src/my file.rs"
/// return Some("src/my file.rs")
-fn get_repeated_file_path_from_diff_line(line: &str) -> Option<String> {
+pub fn get_repeated_file_path_from_diff_line(line: &str) -> Option<String> {
if let Some(line) = line.strip_prefix("diff --git ") {
let line: Vec<&str> = line.graphemes(true).collect();
let midpoint = line.len() / 2;
diff --git a/src/handlers/diff_header_diff.rs b/src/handlers/diff_header_diff.rs
index a79f6e1..f8a007e 100644
--- a/src/handlers/diff_header_diff.rs
+++ b/src/handlers/diff_header_diff.rs
@@ -1,4 +1,5 @@
use crate::delta::{DiffType, InMergeConflict, MergeParents, State, StateMachine};
+use crate::handlers::diff_header::{get_repeated_file_path_from_diff_line, FileEvent};
impl<'a> StateMachine<'a> {
#[inline]
@@ -25,6 +26,19 @@ impl<'a> StateMachine<'a> {
self.handle_pending_line_with_diff_name()?;
self.handled_diff_header_header_line_file_pair = None;
self.diff_line = self.line.clone();
+
+ // Pre-fill header fields from the diff line. For added, removed or renamed files
+ // these are updated precisely on actual header minus and header plus lines.
+ // But for modified binary files which are not added, removed or renamed, there
+ // are no minus and plus lines. Without the code below, in such cases the file names
+ // would remain unchanged from the previous diff, or empty for the very first diff.
+ let name = get_repeated_file_path_from_diff_line(&self.line).unwrap_or_default();
+ self.minus_file = name.clone();
+ self.plus_file = name.clone();
+ self.minus_file_event = FileEvent::Change;
+ self.plus_file_event = FileEvent::Change;
+ self.current_file_pair = Some((self.minus_file.clone(), self.plus_file.clone()));
+
if !self.should_skip_line() {
self.emit_line_unchanged()?;
}
diff --git a/src/handlers/diff_header_misc.rs b/src/handlers/diff_header_misc.rs
index 141767a..c5e4026 100644
--- a/src/handlers/diff_header_misc.rs
+++ b/src/handlers/diff_header_misc.rs
@@ -12,25 +12,26 @@ impl<'a> StateMachine<'a> {
}
pub fn handle_diff_header_misc_line(&mut self) -> std::io::Result<bool> {
- let is_binary: bool = self.test_diff_is_binary();
- let file_missing: bool = self.test_diff_file_missing();
-
- if !file_missing && !is_binary {
+ if !self.test_diff_file_missing() && !self.test_diff_is_binary() {
return Ok(false);
}
- if is_binary {
- match (self.minus_file.as_str(), self.plus_file.as_str()) {
- ("", "") => {
- return self.handle_additional_cases(match self.state {
- State::DiffHeader(_) => self.state.clone(),
- _ => State::DiffHeader(DiffType::Unified),
- });
- }
- ("/dev/null", _) => self.plus_file.push_str(" (binary file)"),
- (_, "/dev/null") => self.minus_file.push_str(" (binary file)"),
- (_, _) => (),
- };
+ if self.test_diff_is_binary() {
+ // Print the "Binary files" line verbatim, if there was no "diff" line, or it
+ // listed different files but was not followed by header minus and plus lines.
+ // This can happen in output of standalone diff or git diff --no-index.
+ if self.minus_file.is_empty() && self.plus_file.is_empty() {
+ self.emit_line_unchanged()?;
+ self.handled_diff_header_header_line_file_pair = self.current_file_pair.clone();
+ return Ok(true);
+ }
+
+ if self.minus_file != "/dev/null" {
+ self.minus_file.push_str(" (binary file)");
+ }
+ if self.plus_file != "/dev/null" {
+ self.plus_file.push_str(" (binary file)");
+ }
return Ok(true);
}