Skip to content

Commit 3cec935

Browse files
committed
feat: add Object::try_into_blob() and into_blob() and Repository::empty_blob()
This way it's easier to assert that an object is actually a blob.
1 parent f712aeb commit 3cec935

File tree

6 files changed

+75
-13
lines changed

6 files changed

+75
-13
lines changed

gix/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ mod types;
158158
#[cfg(any(feature = "excludes", feature = "attributes"))]
159159
pub use types::AttributeStack;
160160
pub use types::{
161-
Commit, Head, Id, Object, ObjectDetached, Reference, Remote, Repository, Tag, ThreadSafeRepository, Tree, Worktree,
161+
Blob, Commit, Head, Id, Object, ObjectDetached, Reference, Remote, Repository, Tag, ThreadSafeRepository, Tree,
162+
Worktree,
162163
};
163164
#[cfg(feature = "attributes")]
164165
pub use types::{Pathspec, PathspecDetached, Submodule};

gix/src/object/impls.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::convert::TryFrom;
22

3-
use crate::{object, Commit, Object, ObjectDetached, Tag, Tree};
3+
use crate::{object, Blob, Commit, Object, ObjectDetached, Tag, Tree};
44

55
impl<'repo> From<Object<'repo>> for ObjectDetached {
66
fn from(mut v: Object<'repo>) -> Self {
@@ -59,11 +59,11 @@ impl<'repo> TryFrom<Object<'repo>> for Commit<'repo> {
5959
type Error = Object<'repo>;
6060

6161
fn try_from(mut value: Object<'repo>) -> Result<Self, Self::Error> {
62-
let handle = value.repo;
62+
let repo = value.repo;
6363
match value.kind {
6464
object::Kind::Commit => Ok(Commit {
6565
id: value.id,
66-
repo: handle,
66+
repo,
6767
data: steal_from_freelist(&mut value.data),
6868
}),
6969
_ => Err(value),
@@ -75,11 +75,11 @@ impl<'repo> TryFrom<Object<'repo>> for Tag<'repo> {
7575
type Error = Object<'repo>;
7676

7777
fn try_from(mut value: Object<'repo>) -> Result<Self, Self::Error> {
78-
let handle = value.repo;
78+
let repo = value.repo;
7979
match value.kind {
8080
object::Kind::Tag => Ok(Tag {
8181
id: value.id,
82-
repo: handle,
82+
repo,
8383
data: steal_from_freelist(&mut value.data),
8484
}),
8585
_ => Err(value),
@@ -91,11 +91,27 @@ impl<'repo> TryFrom<Object<'repo>> for Tree<'repo> {
9191
type Error = Object<'repo>;
9292

9393
fn try_from(mut value: Object<'repo>) -> Result<Self, Self::Error> {
94-
let handle = value.repo;
94+
let repo = value.repo;
9595
match value.kind {
9696
object::Kind::Tree => Ok(Tree {
9797
id: value.id,
98-
repo: handle,
98+
repo,
99+
data: steal_from_freelist(&mut value.data),
100+
}),
101+
_ => Err(value),
102+
}
103+
}
104+
}
105+
106+
impl<'repo> TryFrom<Object<'repo>> for Blob<'repo> {
107+
type Error = Object<'repo>;
108+
109+
fn try_from(mut value: Object<'repo>) -> Result<Self, Self::Error> {
110+
let repo = value.repo;
111+
match value.kind {
112+
object::Kind::Blob => Ok(Blob {
113+
id: value.id,
114+
repo,
99115
data: steal_from_freelist(&mut value.data),
100116
}),
101117
_ => Err(value),

gix/src/object/mod.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::convert::TryInto;
44
use gix_hash::ObjectId;
55
pub use gix_object::Kind;
66

7-
use crate::{Commit, Id, Object, ObjectDetached, Tag, Tree};
7+
use crate::{Blob, Commit, Id, Object, ObjectDetached, Tag, Tree};
88

99
mod errors;
1010
pub(crate) mod cache {
@@ -74,6 +74,14 @@ impl<'repo> Object<'repo> {
7474
}
7575
}
7676

77+
/// Transform this object into a blob, or panic if it is none.
78+
pub fn into_blob(self) -> Blob<'repo> {
79+
match self.try_into() {
80+
Ok(tree) => tree,
81+
Err(this) => panic!("Tried to use {} as tree, but was {}", this.id, this.kind),
82+
}
83+
}
84+
7785
/// Transform this object into a tree, or panic if it is none.
7886
pub fn into_tree(self) -> Tree<'repo> {
7987
match self.try_into() {
@@ -124,6 +132,15 @@ impl<'repo> Object<'repo> {
124132
expected: gix_object::Kind::Tree,
125133
})
126134
}
135+
136+
/// Transform this object into a blob, or return it as part of the `Err` if it is no blob.
137+
pub fn try_into_blob(self) -> Result<Blob<'repo>, try_into::Error> {
138+
self.try_into().map_err(|this: Self| try_into::Error {
139+
id: this.id,
140+
actual: this.kind,
141+
expected: gix_object::Kind::Blob,
142+
})
143+
}
127144
}
128145

129146
impl<'repo> Object<'repo> {

gix/src/repository/object.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use gix_ref::{
1010
};
1111
use smallvec::SmallVec;
1212

13-
use crate::{commit, ext::ObjectIdExt, object, tag, Id, Object, Reference, Tree};
13+
use crate::{commit, ext::ObjectIdExt, object, tag, Blob, Id, Object, Reference, Tree};
1414

1515
/// Methods related to object creation.
1616
impl crate::Repository {
@@ -312,11 +312,23 @@ impl crate::Repository {
312312

313313
/// Return an empty tree object, suitable for [getting changes](crate::Tree::changes()).
314314
///
315-
/// Note that it is special and doesn't physically exist in the object database even though it can be returned.
315+
/// Note that the returned object is special and doesn't necessarily physically exist in the object database.
316316
/// This means that this object can be used in an uninitialized, empty repository which would report to have no objects at all.
317317
pub fn empty_tree(&self) -> Tree<'_> {
318318
self.find_object(gix_hash::ObjectId::empty_tree(self.object_hash()))
319319
.expect("always present")
320320
.into_tree()
321321
}
322+
323+
/// Return an empty blob object.
324+
///
325+
/// Note that the returned object is special and doesn't necessarily physically exist in the object database.
326+
/// This means that this object can be used in an uninitialized, empty repository which would report to have no objects at all.
327+
pub fn empty_blob(&self) -> Blob<'_> {
328+
Blob {
329+
id: gix_hash::ObjectId::empty_blob(self.object_hash()),
330+
data: Vec::new(),
331+
repo: self,
332+
}
333+
}
322334
}

gix/src/types.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,21 @@ impl<'a> Drop for Object<'a> {
4747
}
4848
}
4949

50+
/// A blob along with access to its owning repository.
51+
pub struct Blob<'repo> {
52+
/// The id of the tree
53+
pub id: ObjectId,
54+
/// The blob's data.
55+
pub data: Vec<u8>,
56+
pub(crate) repo: &'repo Repository,
57+
}
58+
59+
impl<'a> Drop for Blob<'a> {
60+
fn drop(&mut self) {
61+
self.repo.reuse_buffer(&mut self.data);
62+
}
63+
}
64+
5065
/// A decoded tree object with access to its owning repository.
5166
pub struct Tree<'repo> {
5267
/// The id of the tree

gix/tests/repository/object.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ fn writes_avoid_io_using_duplicate_check() -> crate::Result {
9090
assert_eq!(new_id, id);
9191
}
9292
Blob => {
93-
let new_id = repo.write_blob(&obj.data)?;
93+
let blob = obj.into_blob();
94+
let new_id = repo.write_blob(&blob.data)?;
9495
assert_eq!(new_id, id);
95-
let new_id = repo.write_blob_stream(std::io::Cursor::new(&obj.data))?;
96+
let new_id = repo.write_blob_stream(std::io::Cursor::new(&blob.data))?;
9697
assert_eq!(new_id, id);
9798
}
9899
}

0 commit comments

Comments
 (0)