@@ -124,8 +124,10 @@ pgit_odb_backend_read_prefix(git_oid *oid_out, void **ptr, size_t *sz, git_objec
124124 }
125125
126126 memcpy (* ptr , bytes , * sz );
127- py_oid_to_git_oid (py_oid_out , oid_out );
127+ size_t oid_len = py_oid_to_git_oid (py_oid_out , oid_out );
128128 Py_DECREF (result );
129+ if (oid_len == 0 )
130+ return GIT_EUSER ;
129131 return 0 ;
130132}
131133
@@ -204,8 +206,10 @@ pgit_odb_backend_exists_prefix(git_oid *out, git_odb_backend *_be,
204206 if (py_oid == NULL )
205207 return git_error_for_exc ();
206208
207- py_oid_to_git_oid (py_oid , out );
209+ size_t oid_len = py_oid_to_git_oid (py_oid , out );
208210 Py_DECREF (py_oid );
211+ if (oid_len == 0 )
212+ return GIT_EUSER ;
209213 return 0 ;
210214}
211215
@@ -224,15 +228,33 @@ pgit_odb_backend_foreach(git_odb_backend *_be,
224228 PyObject * item ;
225229 git_oid oid ;
226230 pgit_odb_backend * be = (pgit_odb_backend * )_be ;
227- PyObject * iterator = PyObject_GetIter ((PyObject * )be -> py_backend );
228- assert (iterator );
231+
232+ /* Call the Python __iter__ method directly. PyObject_GetIter would invoke
233+ * the C tp_iter slot (OdbBackend_as_iter), which calls this function back
234+ * and causes infinite recursion for Python backends. */
235+ PyObject * iter_method = PyObject_GetAttrString ((PyObject * )be -> py_backend , "__iter__" );
236+ if (iter_method == NULL )
237+ return git_error_for_exc ();
238+
239+ PyObject * iterator = PyObject_CallObject (iter_method , NULL );
240+ Py_DECREF (iter_method );
241+ if (iterator == NULL )
242+ return git_error_for_exc ();
229243
230244 while ((item = PyIter_Next (iterator ))) {
231- py_oid_to_git_oid (item , & oid );
232- cb (& oid , payload );
245+ size_t len = py_oid_to_git_oid (item , & oid );
233246 Py_DECREF (item );
247+ if (len == 0 ) {
248+ Py_DECREF (iterator );
249+ return GIT_EUSER ;
250+ }
251+ if (cb (& oid , payload ) != 0 ) {
252+ Py_DECREF (iterator );
253+ return GIT_EUSER ;
254+ }
234255 }
235256
257+ Py_DECREF (iterator );
236258 return git_error_for_exc ();
237259}
238260
@@ -278,7 +300,7 @@ OdbBackend_init(OdbBackend *self, PyObject *args, PyObject *kwds)
278300// custom_backend->backend.freshen = pgit_odb_backend_freshen;
279301// custom_backend->backend.writestream = pgit_odb_backend_writestream;
280302// custom_backend->backend.readstream = pgit_odb_backend_readstream;
281- if (PyIter_Check ((PyObject * )self ))
303+ if (PyObject_HasAttrString ((PyObject * )self , "__iter__" ))
282304 custom_backend -> backend .foreach = pgit_odb_backend_foreach ;
283305
284306 // Cross reference (don't incref because it's something internal)
@@ -321,20 +343,23 @@ PyObject *
321343OdbBackend_as_iter (OdbBackend * self )
322344{
323345 PyObject * accum = PyList_New (0 );
324- PyObject * iter = NULL ;
346+ if (accum == NULL )
347+ return NULL ;
325348
326349 int err = self -> odb_backend -> foreach (self -> odb_backend , OdbBackend_build_as_iter , (void * )accum );
350+ if (err == GIT_EUSER && PyErr_Occurred ()) {
351+ Py_DECREF (accum );
352+ return NULL ;
353+ }
327354 if (err == GIT_EUSER )
328- goto exit ;
355+ err = GIT_ERROR ;
329356
330357 if (err < 0 ) {
331- Error_set ( err );
332- goto exit ;
358+ Py_DECREF ( accum );
359+ return Error_set ( err ) ;
333360 }
334361
335- iter = PyObject_GetIter (accum );
336-
337- exit :
362+ PyObject * iter = PyObject_GetIter (accum );
338363 Py_DECREF (accum );
339364 return iter ;
340365}
@@ -397,8 +422,9 @@ OdbBackend_read_prefix(OdbBackend *self, PyObject *py_hex)
397422
398423 err = self -> odb_backend -> read_prefix (& oid_out , & data , & size , & type , self -> odb_backend , & oid , len );
399424 if (err != 0 ) {
400- Error_set_oid (err , & oid , len );
401- return NULL ;
425+ if (err == GIT_EUSER && PyErr_Occurred ())
426+ return NULL ;
427+ return Error_set_oid (err , & oid , len );
402428 }
403429
404430 PyObject * py_oid_out = git_oid_to_python (& oid_out );
@@ -492,8 +518,11 @@ OdbBackend_exists_prefix(OdbBackend *self, PyObject *py_hex)
492518 git_oid out ;
493519 result = self -> odb_backend -> exists_prefix (& out , self -> odb_backend , & oid , len );
494520
495- if (result < 0 )
521+ if (result < 0 ) {
522+ if (result == GIT_EUSER && PyErr_Occurred ())
523+ return NULL ;
496524 return Error_set (result );
525+ }
497526
498527 return git_oid_to_python (& out );
499528}
0 commit comments