diff --git a/src/git.rs b/src/git.rs index 2f72e19c7..feeacad59 100644 --- a/src/git.rs +++ b/src/git.rs @@ -357,7 +357,12 @@ impl Source { .context(FileError::ReadFailed)? .content() .to_vec(), - Self::WorkingFile { path, .. } => std::fs::read(path).context(FileError::ReadFailed)?, + Self::WorkingFile { path, .. } => { + // Apply Git's clean filters (autocrlf, eol, ident) like `git diff`. + let id = repo.blob_path(path).context(FileError::ReadFailed)?; + let blob = repo.find_blob(id).context(FileError::ReadFailed)?; + blob.content().to_vec() + } Self::Absent => unreachable!(), }; Ok(bytes) @@ -419,6 +424,8 @@ impl DiffSession { pipeline: &Pipeline, ) -> Result { let repo = Repository::open(workspace)?; + // Takes the blobs `Source::read` writes, keeping them out of .git. + repo.odb()?.add_new_mempack_backend(1000)?; let comparison = comparison.resolve(&repo)?; let pending = { let diff = comparison.diff(&repo, files)?; diff --git a/tests/view.rs b/tests/view.rs index 2ff7e94ef..27e6e2862 100644 --- a/tests/view.rs +++ b/tests/view.rs @@ -278,3 +278,34 @@ fn git_binary_files_stream_as_diff_records_with_side_sizes() { serde_json::json!({"type": "binary", "lhs": {"size": 8}, "rhs": {"size": 4}}) ); } + +#[test] +fn working_tree_files_go_through_git_clean_filters() { + let fixture = Fixture::new(); + fixture + .repo + .config() + .unwrap() + .set_bool("core.autocrlf", true) + .unwrap(); + let lines: Vec = (1..=20).map(|i| format!("doc line {i}")).collect(); + fixture.write("notes.md", &(lines.join("\n") + "\n")); + let base = fixture.commit(); + let mut edited = lines.clone(); + edited[9] = "doc line 10 CHANGED".into(); + fixture.write("notes.md", &(edited.join("\r\n") + "\r\n")); + let output = fixture.diffr(&[&base, "--format", "ndjson"]); + assert!( + output.status.success(), + "{}", + String::from_utf8_lossy(&output.stderr) + ); + let records = records(&output); + let notes = record(&records, "notes.md"); + assert_eq!(notes["diff"]["rhs"]["text"], edited.join("\n") + "\n"); + let changed: Vec = regions(notes, "rhs") + .iter() + .flat_map(|region| region["changed"].as_array().cloned().unwrap_or_default()) + .collect(); + assert!(changed.iter().all(|span| span["line"] == 9), "{changed:?}"); +}