Skip to content

Commit 6a6b9ee

Browse files
committed
feat: Add OdbBackend::foreach
1 parent 88a8919 commit 6a6b9ee

File tree

1 file changed

+71
-1
lines changed

1 file changed

+71
-1
lines changed

src/odb_backend.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,28 @@ pub trait OdbBackend: Sized {
392392
unimplemented!("OdbBackend::open_write_stream")
393393
}
394394

395-
// TODO: fn foreach()
395+
/// Iterates through all objects this backend knows of.
396+
///
397+
/// Corresponds to the `foreach` function of [`git_odb_backend`].
398+
/// Requires that [`SupportedOperations::FOREACH`] is present in the value returned from
399+
/// [`supported_operations`].
400+
///
401+
/// The default implementation of this method panics.
402+
///
403+
/// # Implementation notes
404+
///
405+
/// For each object in this backend, `callback` should be invoked with the object's Oid once.
406+
/// See [`ForeachCallback::invoke`].
407+
///
408+
/// # Errors
409+
///
410+
/// If the callback returns an error, the backend SHOULD propagate that error instead of
411+
/// continuing iteration.
412+
///
413+
/// See [`OdbBackend`] for more recommendations.
414+
fn foreach(&mut self, ctx: &OdbBackendContext, callback: ForeachCallback) -> Result<(), Error> {
415+
unimplemented!("OdbBackend::foreach")
416+
}
396417
}
397418

398419
bitflags! {
@@ -827,6 +848,37 @@ impl<B: OdbBackend> OdbWriteStream<B> for Infallible {
827848
}
828849
}
829850

851+
/// Callback used in calls to [`OdbBackend::foreach`].
852+
///
853+
/// A wrapper for [`git_odb_foreach_cb`](raw::git_odb_foreach_cb).
854+
pub struct ForeachCallback {
855+
callback: raw::git_odb_foreach_cb,
856+
payload: *mut libc::c_void,
857+
}
858+
impl ForeachCallback {
859+
/// Invokes this callback.
860+
///
861+
/// # Arguments
862+
///
863+
/// `oid` should be the ID of the object that was iterated over.
864+
///
865+
/// # Return value
866+
///
867+
/// Returns `Ok(())` if the callback returns 0.
868+
/// Returns an error if the callback returns a non-zero integer.
869+
pub fn invoke(&mut self, oid: &Oid) -> Result<(), Error> {
870+
let code = match self.callback {
871+
Some(callback) => callback(oid.raw(), self.payload),
872+
None => return Ok(()), // maybe this should be an error
873+
};
874+
if code != 0 {
875+
Err(Error::last_error(code))
876+
} else {
877+
Ok(())
878+
}
879+
}
880+
}
881+
830882
/// Context struct passed to [`OdbReadStream`] and [`OdbWriteStream`]'s methods.
831883
pub struct OdbStreamContext<B: OdbBackend> {
832884
backend_ptr: ptr::NonNull<Backend<B>>,
@@ -922,6 +974,7 @@ impl<'a, B: OdbBackend> CustomOdbBackend<'a, B> {
922974
op_if!(exists if EXISTS);
923975
op_if!(exists_prefix if EXISTS_PREFIX);
924976
op_if!(refresh if REFRESH);
977+
op_if!(foreach if FOREACH);
925978
op_if!(writepack if WRITE_PACK);
926979
op_if!(writemidx if WRITE_MULTIPACK_INDEX);
927980
op_if!(freshen if FRESHEN);
@@ -1187,6 +1240,23 @@ impl<B: OdbBackend> Backend<B> {
11871240
raw::GIT_OK
11881241
}
11891242

1243+
extern "C" fn foreach(
1244+
backend_ptr: *mut raw::git_odb_backend,
1245+
foreach_cb: raw::git_odb_foreach_cb,
1246+
foreach_cb_payload: *mut libc::c_void,
1247+
) -> libc::c_int {
1248+
let backend = unsafe { backend_ptr.cast::<Self>().as_mut().unwrap() };
1249+
let context = OdbBackendContext { backend_ptr };
1250+
let callback = ForeachCallback {
1251+
callback: foreach_cb,
1252+
payload: foreach_cb_payload,
1253+
};
1254+
if let Err(e) = backend.inner.foreach(&context, callback) {
1255+
return unsafe { e.raw_set_git_error() };
1256+
}
1257+
raw::GIT_OK
1258+
}
1259+
11901260
extern "C" fn writepack(
11911261
out_writepack_ptr: *mut *mut raw::git_odb_writepack,
11921262
backend_ptr: *mut raw::git_odb_backend,

0 commit comments

Comments
 (0)