Skip to content

Commit 787a9aa

Browse files
committed
feat: Add Repository::has_object() as a high-level alternative.
Previously, one would have to call `repo.objects.contains()`, which is fine, but this method is necessary for symmetry of the API and one shouldn't have to drop down a level to do this. This method also knows empty trees as special case.
1 parent 3cec935 commit 787a9aa

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

gix/src/repository/object.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl crate::Repository {
2626
#[momo]
2727
pub fn find_object(&self, id: impl Into<ObjectId>) -> Result<Object<'_>, object::find::existing::Error> {
2828
let id = id.into();
29-
if id == gix_hash::ObjectId::empty_tree(self.object_hash()) {
29+
if id == ObjectId::empty_tree(self.object_hash()) {
3030
return Ok(Object {
3131
id,
3232
kind: gix_object::Kind::Tree,
@@ -46,7 +46,7 @@ impl crate::Repository {
4646
#[momo]
4747
pub fn find_header(&self, id: impl Into<ObjectId>) -> Result<gix_odb::find::Header, object::find::existing::Error> {
4848
let id = id.into();
49-
if id == gix_hash::ObjectId::empty_tree(self.object_hash()) {
49+
if id == ObjectId::empty_tree(self.object_hash()) {
5050
return Ok(gix_odb::find::Header::Loose {
5151
kind: gix_object::Kind::Tree,
5252
size: 0,
@@ -55,6 +55,25 @@ impl crate::Repository {
5555
self.objects.header(id)
5656
}
5757

58+
/// Return `true` if `id` exists in the object database.
59+
///
60+
/// # Performance
61+
///
62+
/// This method can be slow if the underlying [object database](crate::Repository::objects) has
63+
/// an unsuitable [RefreshMode](gix_odb::store::RefreshMode) and `id` is not likely to exist.
64+
/// Use [`repo.objects.refresh_never()`](gix_odb::store::Handle::refresh_never) to avoid expensive
65+
/// IO-bound refreshes if an object wasn't found.
66+
#[doc(alias = "exists", alias = "git2")]
67+
#[momo]
68+
pub fn has_object(&self, id: impl AsRef<gix_hash::oid>) -> bool {
69+
let id = id.as_ref();
70+
if id == ObjectId::empty_tree(self.object_hash()) {
71+
true
72+
} else {
73+
self.objects.contains(id)
74+
}
75+
}
76+
5877
/// Obtain information about an object without fully decoding it, or `None` if the object doesn't exist.
5978
///
6079
/// Note that despite being cheaper than [`Self::try_find_object()`], there is still some effort traversing delta-chains.
@@ -64,7 +83,7 @@ impl crate::Repository {
6483
id: impl Into<ObjectId>,
6584
) -> Result<Option<gix_odb::find::Header>, object::find::Error> {
6685
let id = id.into();
67-
if id == gix_hash::ObjectId::empty_tree(self.object_hash()) {
86+
if id == ObjectId::empty_tree(self.object_hash()) {
6887
return Ok(Some(gix_odb::find::Header::Loose {
6988
kind: gix_object::Kind::Tree,
7089
size: 0,
@@ -77,7 +96,7 @@ impl crate::Repository {
7796
#[momo]
7897
pub fn try_find_object(&self, id: impl Into<ObjectId>) -> Result<Option<Object<'_>>, object::find::Error> {
7998
let id = id.into();
80-
if id == gix_hash::ObjectId::empty_tree(self.object_hash()) {
99+
if id == ObjectId::empty_tree(self.object_hash()) {
81100
return Ok(Some(Object {
82101
id,
83102
kind: gix_object::Kind::Tree,
@@ -236,7 +255,7 @@ impl crate::Repository {
236255
reference: FullName,
237256
message: &str,
238257
tree: ObjectId,
239-
parents: SmallVec<[gix_hash::ObjectId; 1]>,
258+
parents: SmallVec<[ObjectId; 1]>,
240259
) -> Result<Id<'_>, commit::Error> {
241260
use gix_ref::{
242261
transaction::{Change, RefEdit},
@@ -310,12 +329,12 @@ impl crate::Repository {
310329
self.commit_as(committer, author, reference, message, tree, parents)
311330
}
312331

313-
/// Return an empty tree object, suitable for [getting changes](crate::Tree::changes()).
332+
/// Return an empty tree object, suitable for [getting changes](Tree::changes()).
314333
///
315334
/// Note that the returned object is special and doesn't necessarily physically exist in the object database.
316335
/// This means that this object can be used in an uninitialized, empty repository which would report to have no objects at all.
317336
pub fn empty_tree(&self) -> Tree<'_> {
318-
self.find_object(gix_hash::ObjectId::empty_tree(self.object_hash()))
337+
self.find_object(ObjectId::empty_tree(self.object_hash()))
319338
.expect("always present")
320339
.into_tree()
321340
}

gix/tests/repository/object.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ fn writes_avoid_io_using_duplicate_check() -> crate::Result {
6868

6969
for id in repo.objects.iter()? {
7070
let id = id?;
71+
assert!(repo.has_object(id));
7172
let obj = repo.find_object(id)?;
7273
let header = repo.find_header(id)?;
7374
assert_eq!(obj.kind, header.kind(), "header and object agree");
@@ -156,6 +157,7 @@ mod find {
156157
let repo = basic_repo()?;
157158
let empty_tree = gix::hash::ObjectId::empty_tree(repo.object_hash());
158159
assert_eq!(repo.find_object(empty_tree)?.into_tree().iter().count(), 0);
160+
assert!(repo.has_object(empty_tree));
159161
assert_eq!(
160162
repo.find_header(empty_tree)?,
161163
gix_odb::find::Header::Loose {

0 commit comments

Comments
 (0)