Skip to content

Commit d2389f9

Browse files
committed
fix: when no worktree-root is specified, fail instead of using empty blobs.
1 parent 5a1b3d6 commit d2389f9

File tree

4 files changed

+51
-19
lines changed

4 files changed

+51
-19
lines changed

gix-diff/src/blob/pipeline.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ pub mod convert_to_diffable {
157157
ConvertToGit(#[from] gix_filter::pipeline::convert::to_git::Error),
158158
#[error("Memory allocation failed")]
159159
OutOfMemory(#[from] TryReserveError),
160+
#[error("An ObjectId wasn't provided, but a worktree root wasn't provided either for reading from disk")]
161+
UnsetWorktreeRoot,
160162
}
161163
}
162164

@@ -208,6 +210,7 @@ impl Pipeline {
208210
///
209211
/// If `id` [is null](gix_hash::ObjectId::is_null()) or the file in question doesn't exist in the worktree in case
210212
/// [a root](WorktreeRoots) is present, then `out` will be left cleared and [Outcome::data] will be `None`.
213+
/// Note that it is an error to not provide a workdir root *and* a null `id`.
211214
///
212215
/// Note that `mode` is trusted, and we will not re-validate that the entry in the worktree actually is of that mode.
213216
///
@@ -383,9 +386,10 @@ impl Pipeline {
383386
Ok(Outcome { driver_index, data })
384387
}
385388
None => {
386-
let data = if id.is_null() {
387-
None
388-
} else {
389+
if id.is_null() {
390+
return Err(convert_to_diffable::Error::UnsetWorktreeRoot);
391+
}
392+
let data = {
389393
let header = objects
390394
.try_header(id)
391395
.map_err(gix_object::find::existing_object::Error::Find)?

gix-diff/src/blob/platform.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,12 @@ impl Platform {
369369
/// depending on whether or not a [worktree root](pipeline::WorktreeRoots) is set for the resource of `kind`,
370370
/// with resources with worktree roots using the `rela_path` as unique identifier.
371371
///
372+
/// ### Warning: Unbounded Memory Caching
373+
///
374+
/// As the instance is meant to be used for repeated diffs during rename-checking, it is caching diffable objects
375+
/// in memory.
376+
/// Be sure to either not reuse the instance, or call [clear_resource_cache*()](Self::clear_resource_cache()) regularly.
377+
///
372378
/// ### Important
373379
///
374380
/// If an error occurs, the previous resource of `kind` will be cleared, preventing further diffs

gix-diff/tests/diff/blob/pipeline.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -283,19 +283,23 @@ pub(crate) mod convert_to_diffable {
283283
drop(tmp);
284284

285285
buf.push(1);
286-
let out = filter.convert_to_diffable(
287-
&null,
288-
EntryKind::Blob,
289-
a_name.into(),
290-
ResourceKind::NewOrDestination,
291-
&mut |_, _| {},
292-
&gix_object::find::Never,
293-
pipeline::Mode::default(),
294-
&mut buf,
295-
)?;
286+
let err = filter
287+
.convert_to_diffable(
288+
&null,
289+
EntryKind::Blob,
290+
a_name.into(),
291+
ResourceKind::NewOrDestination,
292+
&mut |_, _| {},
293+
&gix_object::find::Never,
294+
pipeline::Mode::default(),
295+
&mut buf,
296+
)
297+
.unwrap_err();
296298

297-
assert!(out.driver_index.is_none(), "there was no driver");
298-
assert_eq!(out.data, None);
299+
assert_eq!(
300+
err.to_string(),
301+
"An ObjectId wasn't provided, but a worktree root wasn't provided either for reading from disk"
302+
);
299303
assert_eq!(buf.len(), 0, "it's always cleared before any potential use");
300304

301305
Ok(())
@@ -692,6 +696,7 @@ pub(crate) mod convert_to_diffable {
692696
assert_eq!(buf.len(), 0, "always cleared");
693697

694698
buf.push(1);
699+
filter.roots.new_root = filter.roots.old_root.clone();
695700
let out = filter.convert_to_diffable(
696701
&null,
697702
EntryKind::Link,
@@ -707,6 +712,7 @@ pub(crate) mod convert_to_diffable {
707712
assert_eq!(out.driver_index, Some(4), "despite missing, we get driver information");
708713
assert_eq!(out.data, None);
709714
assert_eq!(buf.len(), 0, "always cleared");
715+
filter.roots.new_root.take();
710716

711717
buf.push(1);
712718
let id = db.insert("link-target");

gix-diff/tests/diff/blob/platform.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ fn diff_skipped_due_to_external_command_and_enabled_option() -> crate::Result {
293293

294294
#[test]
295295
fn source_and_destination_do_not_exist() -> crate::Result {
296-
let mut platform = new_platform(None, pipeline::Mode::default());
296+
let mut platform = new_platform_multiroot(None, pipeline::Mode::default(), PopulateRoot::OldAndNew);
297297
platform.set_resource(
298298
gix_hash::Kind::Sha1.null(),
299299
EntryKind::Blob,
@@ -305,7 +305,7 @@ fn source_and_destination_do_not_exist() -> crate::Result {
305305
platform.set_resource(
306306
gix_hash::Kind::Sha1.null(),
307307
EntryKind::BlobExecutable,
308-
"a".into(),
308+
"also-missing".into(),
309309
ResourceKind::NewOrDestination,
310310
&gix_object::find::Never,
311311
)?;
@@ -339,7 +339,7 @@ fn source_and_destination_do_not_exist() -> crate::Result {
339339
.expect("resources set")
340340
),
341341
format!(
342-
r#"{}"test" "missing" "/dev/null" "." "." "/dev/null" "." "." "a""#,
342+
r#"{}"test" "missing" "/dev/null" "." "." "/dev/null" "." "." "also-missing""#,
343343
(!cfg!(windows))
344344
.then_some(r#"GIT_DIFF_PATH_COUNTER="1" GIT_DIFF_PATH_TOTAL="1" GIT_DIR="." "#)
345345
.unwrap_or_default()
@@ -371,6 +371,19 @@ fn invalid_resource_types() {
371371
fn new_platform(
372372
drivers: impl IntoIterator<Item = gix_diff::blob::Driver>,
373373
mode: gix_diff::blob::pipeline::Mode,
374+
) -> Platform {
375+
new_platform_multiroot(drivers, mode, PopulateRoot::Old)
376+
}
377+
378+
enum PopulateRoot {
379+
OldAndNew,
380+
Old,
381+
}
382+
383+
fn new_platform_multiroot(
384+
drivers: impl IntoIterator<Item = gix_diff::blob::Driver>,
385+
mode: gix_diff::blob::pipeline::Mode,
386+
populate_root: PopulateRoot,
374387
) -> Platform {
375388
let root = gix_testtools::scripted_fixture_read_only_standalone("make_blob_repo.sh").expect("valid fixture");
376389
let attributes = gix_worktree::Stack::new(
@@ -388,7 +401,10 @@ fn new_platform(
388401
let filter = gix_diff::blob::Pipeline::new(
389402
pipeline::WorktreeRoots {
390403
old_root: Some(root.clone()),
391-
new_root: None,
404+
new_root: match populate_root {
405+
PopulateRoot::OldAndNew => Some(root.clone()),
406+
PopulateRoot::Old => None,
407+
},
392408
},
393409
gix_filter::Pipeline::default(),
394410
drivers.into_iter().collect(),

0 commit comments

Comments
 (0)