@@ -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
398419bitflags ! {
@@ -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.
831883pub 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