Skip to content

Commit 223278d

Browse files
committed
fix: assure binary-detection also works if ODB files are below the big-file threshold.
1 parent abcfb65 commit 223278d

File tree

2 files changed

+72
-3
lines changed

2 files changed

+72
-3
lines changed

gix-diff/src/blob/pipeline.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,11 @@ impl Pipeline {
377377
.try_header(id)
378378
.map_err(gix_object::find::existing_object::Error::Find)?
379379
.ok_or_else(|| gix_object::find::existing_object::Error::NotFound { oid: id.to_owned() })?;
380-
if is_binary.is_none() && self.options.large_file_threshold_bytes > 0 {
381-
is_binary = Some(header.size > self.options.large_file_threshold_bytes);
380+
if is_binary.is_none()
381+
&& self.options.large_file_threshold_bytes > 0
382+
&& header.size > self.options.large_file_threshold_bytes
383+
{
384+
is_binary = Some(true);
382385
};
383386
let data = if is_binary == Some(true) {
384387
Data::Binary { size: header.size }
@@ -425,7 +428,18 @@ impl Pipeline {
425428
})?;
426429
match cmd_and_file {
427430
Some((cmd, mut tmp_file)) => {
428-
tmp_file.write_all(out).map_err(|err| {
431+
match res {
432+
ToWorktreeOutcome::Unchanged(buf) | ToWorktreeOutcome::Buffer(buf) => {
433+
tmp_file.write_all(buf)
434+
}
435+
ToWorktreeOutcome::Process(MaybeDelayed::Immediate(mut stream)) => {
436+
std::io::copy(&mut stream, &mut tmp_file).map(|_| ())
437+
}
438+
ToWorktreeOutcome::Process(MaybeDelayed::Delayed(_)) => {
439+
unreachable!("we prohibit this")
440+
}
441+
}
442+
.map_err(|err| {
429443
convert_to_diffable::Error::CreateTempfile {
430444
source: err,
431445
rela_path: rela_path.to_owned(),

gix-diff/tests/blob/pipeline.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,61 @@ pub(crate) mod convert_to_diffable {
9393
Ok(())
9494
}
9595

96+
#[test]
97+
fn binary_below_large_file_threshold() -> crate::Result {
98+
let tmp = gix_testtools::tempfile::TempDir::new()?;
99+
let mut filter = gix_diff::blob::Pipeline::new(
100+
WorktreeRoots {
101+
old_root: None,
102+
new_root: Some(tmp.path().to_owned()),
103+
},
104+
gix_filter::Pipeline::default(),
105+
vec![],
106+
gix_diff::blob::pipeline::Options {
107+
large_file_threshold_bytes: 5,
108+
..default_options()
109+
},
110+
);
111+
112+
let does_not_matter = gix_hash::Kind::Sha1.null();
113+
let mut buf = Vec::new();
114+
let a_name = "a";
115+
let large_content = "a\0b";
116+
std::fs::write(tmp.path().join(a_name), large_content.as_bytes())?;
117+
let out = filter.convert_to_diffable(
118+
&does_not_matter,
119+
EntryKind::BlobExecutable,
120+
a_name.into(),
121+
ResourceKind::NewOrDestination,
122+
&mut |_, _| {},
123+
&gix_object::find::Never,
124+
pipeline::Mode::default(),
125+
&mut buf,
126+
)?;
127+
assert!(out.driver_index.is_none(), "there was no driver");
128+
assert_eq!(out.data, Some(pipeline::Data::Binary { size: 3 }), "detected in buffer");
129+
assert_eq!(buf.len(), 0, "it should avoid querying that data in the first place");
130+
131+
let mut db = ObjectDb::default();
132+
let id = db.insert(large_content);
133+
let out = filter.convert_to_diffable(
134+
&id,
135+
EntryKind::Blob,
136+
a_name.into(),
137+
ResourceKind::OldOrSource,
138+
&mut |_, _| {},
139+
&db,
140+
pipeline::Mode::default(),
141+
&mut buf,
142+
)?;
143+
144+
assert!(out.driver_index.is_none(), "there was no driver");
145+
assert_eq!(out.data, Some(pipeline::Data::Binary { size: 3 }));
146+
assert_eq!(buf.len(), 0, "it should avoid querying that data in the first place");
147+
148+
Ok(())
149+
}
150+
96151
#[test]
97152
fn above_large_file_threshold() -> crate::Result {
98153
let tmp = gix_testtools::tempfile::TempDir::new()?;

0 commit comments

Comments
 (0)