From ca9988284c48e96210ebdc6417b75cc6e8e3b396 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Sep 2025 05:20:19 +0200 Subject: [PATCH 1/2] Implement WriteTo trait for gix::Blob with comprehensive tests Co-authored-by: Byron <63622+Byron@users.noreply.github.com> --- gix/src/object/impls.rs | 14 ++++++ gix/tests/gix/repository/object.rs | 74 ++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/gix/src/object/impls.rs b/gix/src/object/impls.rs index 941b42dacb6..25ed79cc3d6 100644 --- a/gix/src/object/impls.rs +++ b/gix/src/object/impls.rs @@ -150,6 +150,20 @@ impl std::fmt::Debug for Object<'_> { } } +impl<'repo> gix_object::WriteTo for Blob<'repo> { + fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> { + out.write_all(&self.data) + } + + fn kind(&self) -> gix_object::Kind { + gix_object::Kind::Blob + } + + fn size(&self) -> u64 { + self.data.len() as u64 + } +} + /// In conjunction with the handles free list, leaving an empty Vec in place of the original causes it to not be /// returned to the free list. fn steal_from_freelist(data: &mut Vec) -> Vec { diff --git a/gix/tests/gix/repository/object.rs b/gix/tests/gix/repository/object.rs index 3ef570606a6..4ef9e04c357 100644 --- a/gix/tests/gix/repository/object.rs +++ b/gix/tests/gix/repository/object.rs @@ -292,6 +292,80 @@ mod write_object { ); Ok(()) } + + #[test] + fn blob_write_to_implementation() -> crate::Result { + let repo = empty_bare_in_memory_repo()?; + let test_data = b"hello world"; + + // Create a blob directly to test our WriteTo implementation + let blob_id = repo.write_blob(test_data)?; + let blob = repo.find_object(blob_id)?.into_blob(); + + // Test that we can use the blob with write_object (which requires WriteTo) + let written_id = repo.write_object(blob)?; + + // The written blob should have the same ID as the original + assert_eq!(blob_id, written_id, "WriteTo implementation should produce identical blob"); + + // Verify the content is correct + let retrieved_blob = repo.find_object(written_id)?.into_blob(); + assert_eq!(retrieved_blob.data, test_data, "Blob data should be preserved"); + + Ok(()) + } + + #[test] + fn blob_write_to_properties() -> crate::Result { + let repo = empty_bare_in_memory_repo()?; + let test_data = b"test data for WriteTo properties"; + + // Create a blob to test WriteTo trait methods + let blob_id = repo.write_blob(test_data)?; + let blob = repo.find_object(blob_id)?.into_blob(); + + // Test WriteTo trait methods directly + use gix_object::WriteTo; + + // Test kind() method + assert_eq!(blob.kind(), gix_object::Kind::Blob, "kind() should return Blob"); + + // Test size() method + assert_eq!(blob.size(), test_data.len() as u64, "size() should return data length"); + + // Test write_to() method + let mut buffer = Vec::new(); + blob.write_to(&mut buffer)?; + assert_eq!(buffer, test_data, "write_to() should write blob data verbatim"); + + Ok(()) + } + + #[test] + fn blob_write_to_empty_blob() -> crate::Result { + let repo = empty_bare_in_memory_repo()?; + let empty_data = b""; + + // Create an empty blob to test edge case + let blob_id = repo.write_blob(empty_data)?; + let blob = repo.find_object(blob_id)?.into_blob(); + + // Test WriteTo trait methods with empty blob + use gix_object::WriteTo; + + assert_eq!(blob.kind(), gix_object::Kind::Blob, "kind() should return Blob for empty blob"); + assert_eq!(blob.size(), 0, "size() should return 0 for empty blob"); + + let mut buffer = Vec::new(); + blob.write_to(&mut buffer)?; + assert_eq!(buffer, empty_data, "write_to() should write empty data for empty blob"); + + // Test that we can write the empty blob using write_object + let written_id = repo.write_object(blob)?; + assert_eq!(blob_id, written_id, "WriteTo implementation should work for empty blobs"); + + Ok(()) + } } mod write_blob { From 3499050a972efeba3524748af463fc0f29a1b509 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 15 Sep 2025 05:13:02 +0200 Subject: [PATCH 2/2] refactor --- gix/src/object/impls.rs | 5 +- gix/tests/gix/repository/object.rs | 75 ++++-------------------------- 2 files changed, 12 insertions(+), 68 deletions(-) diff --git a/gix/src/object/impls.rs b/gix/src/object/impls.rs index 25ed79cc3d6..f8c8894123f 100644 --- a/gix/src/object/impls.rs +++ b/gix/src/object/impls.rs @@ -150,7 +150,10 @@ impl std::fmt::Debug for Object<'_> { } } -impl<'repo> gix_object::WriteTo for Blob<'repo> { +/// Note that the `data` written here might not correspond to the `id` of the `Blob` anymore if it was modified. +/// Also, this is merely for convenience when writing empty blobs to the ODB. For writing any blob, use +/// [`Repository::write_blob()`](crate::Repository::write_blob()). +impl gix_object::WriteTo for Blob<'_> { fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> { out.write_all(&self.data) } diff --git a/gix/tests/gix/repository/object.rs b/gix/tests/gix/repository/object.rs index 4ef9e04c357..89b0e6419a5 100644 --- a/gix/tests/gix/repository/object.rs +++ b/gix/tests/gix/repository/object.rs @@ -262,7 +262,7 @@ mod write_object { let oid = repo.write_object(gix::objs::TreeRef::empty())?; assert_eq!( oid, - gix::hash::ObjectId::empty_tree(repo.object_hash()), + repo.object_hash().empty_tree(), "it produces a well-known empty tree id" ); Ok(()) @@ -277,7 +277,7 @@ mod write_object { time: Default::default(), }; let commit = gix::objs::Commit { - tree: gix::hash::ObjectId::empty_tree(repo.object_hash()), + tree: repo.object_hash().empty_tree(), author: actor.clone(), committer: actor, parents: Default::default(), @@ -296,74 +296,15 @@ mod write_object { #[test] fn blob_write_to_implementation() -> crate::Result { let repo = empty_bare_in_memory_repo()?; - let test_data = b"hello world"; - + let blob = repo.empty_blob(); + // Create a blob directly to test our WriteTo implementation - let blob_id = repo.write_blob(test_data)?; - let blob = repo.find_object(blob_id)?.into_blob(); - - // Test that we can use the blob with write_object (which requires WriteTo) - let written_id = repo.write_object(blob)?; - - // The written blob should have the same ID as the original - assert_eq!(blob_id, written_id, "WriteTo implementation should produce identical blob"); - - // Verify the content is correct - let retrieved_blob = repo.find_object(written_id)?.into_blob(); - assert_eq!(retrieved_blob.data, test_data, "Blob data should be preserved"); - - Ok(()) - } + let actual_id = repo.write_object(&blob)?; + let actual_blob = repo.find_object(actual_id)?.into_blob(); + assert_eq!(actual_id, repo.object_hash().empty_blob()); - #[test] - fn blob_write_to_properties() -> crate::Result { - let repo = empty_bare_in_memory_repo()?; - let test_data = b"test data for WriteTo properties"; - - // Create a blob to test WriteTo trait methods - let blob_id = repo.write_blob(test_data)?; - let blob = repo.find_object(blob_id)?.into_blob(); - - // Test WriteTo trait methods directly - use gix_object::WriteTo; - - // Test kind() method - assert_eq!(blob.kind(), gix_object::Kind::Blob, "kind() should return Blob"); - - // Test size() method - assert_eq!(blob.size(), test_data.len() as u64, "size() should return data length"); - - // Test write_to() method - let mut buffer = Vec::new(); - blob.write_to(&mut buffer)?; - assert_eq!(buffer, test_data, "write_to() should write blob data verbatim"); - - Ok(()) - } + assert_eq!(actual_blob.data, blob.data); - #[test] - fn blob_write_to_empty_blob() -> crate::Result { - let repo = empty_bare_in_memory_repo()?; - let empty_data = b""; - - // Create an empty blob to test edge case - let blob_id = repo.write_blob(empty_data)?; - let blob = repo.find_object(blob_id)?.into_blob(); - - // Test WriteTo trait methods with empty blob - use gix_object::WriteTo; - - assert_eq!(blob.kind(), gix_object::Kind::Blob, "kind() should return Blob for empty blob"); - assert_eq!(blob.size(), 0, "size() should return 0 for empty blob"); - - let mut buffer = Vec::new(); - blob.write_to(&mut buffer)?; - assert_eq!(buffer, empty_data, "write_to() should write empty data for empty blob"); - - // Test that we can write the empty blob using write_object - let written_id = repo.write_object(blob)?; - assert_eq!(blob_id, written_id, "WriteTo implementation should work for empty blobs"); - Ok(()) } }