Index: subversion/bindings/swig/svn_ra.i =================================================================== --- subversion/bindings/swig/svn_ra.i (revision 20114) +++ subversion/bindings/swig/svn_ra.i (working copy) @@ -166,6 +166,14 @@ } #endif +#ifdef SWIGPYTHON +%typemap(in) (svn_ra_file_rev_handler_t handler, void *handler_baton) +{ + $1 = svn_swig_py_ra_file_rev_handler_func; + $2 = (void *)$input; +} +#endif + /* ----------------------------------------------------------------------- */ %{ Index: subversion/bindings/swig/python/tests/ra.py =================================================================== --- subversion/bindings/swig/python/tests/ra.py (revision 20114) +++ subversion/bindings/swig/python/tests/ra.py (working copy) @@ -67,6 +67,19 @@ child = delta.editor_invoke_add_directory(editor, "bla", root, None, 0) delta.editor_invoke_close_edit(editor, edit_baton) + def test_get_file_revs(self): + def rev_handler(path, rev, rev_props, prop_diffs, pool): + self.assert_(rev == 2 or rev == 3) + self.assertEqual(path, "/trunk/README.txt") + if rev == 2: + self.assertEqual(rev_props, {'svn:log': 'Added README.', 'svn:author': 'john', 'svn:date': '2005-04-01T13:12:18.216267Z'}) + self.assertEqual(prop_diffs, {}) + elif rev == 3: + self.assertEqual(rev_props, {'svn:log': 'Fixed README.\n', 'svn:author': 'kate', 'svn:date': '2005-04-01T13:24:58.234643Z'}) + self.assertEqual(prop_diffs, {'svn:mime-type': 'text/plain', 'svn:eol-style': 'native'}) + + ra.get_file_revs(self.ra_ctx, "trunk/README.txt", 0, 10, rev_handler) + def test_update(self): class TestEditor(delta.Editor): pass Index: subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c =================================================================== --- subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c (revision 20114) +++ subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c (working copy) @@ -524,7 +524,47 @@ return convert_hash(hash, convert_svn_string_t, NULL, NULL); } +PyObject *svn_swig_py_proparray_to_dict(const apr_array_header_t *array) +{ + PyObject *dict = PyDict_New(); + int i; + for (i = 0; i < array->nelts; ++i) { + svn_prop_t prop; + PyObject *py_key, *py_value; + + prop = APR_ARRAY_IDX(array, i, svn_prop_t); + + py_key = PyString_FromString(prop.name); + if (py_key == NULL) + goto error; + + if (prop.value == NULL) + { + py_value = Py_None; + } + else + { + py_value = PyString_FromStringAndSize((void *)prop.value->data, + prop.value->len); + if (py_value == NULL) { + Py_XDECREF(py_key); + goto error; + } + } + + PyDict_SetItem(dict, py_key, py_value); + } + + return dict; + + error: + Py_DECREF(dict); + return NULL; + +} + + PyObject *svn_swig_py_locationhash_to_dict(apr_hash_t *hash) { /* Need special code for this because of the darned svn_revnum_t @@ -2231,4 +2271,69 @@ return err; } +svn_error_t *svn_swig_py_ra_file_rev_handler_func( + void *baton, + const char *path, + svn_revnum_t rev, + apr_hash_t *rev_props, + svn_txdelta_window_handler_t *delta_handler, + void **delta_baton, + apr_array_header_t *prop_diffs, + apr_pool_t *pool) +{ + PyObject *handler = baton; + PyObject *result, *py_rev_props = NULL, *py_prop_diffs = NULL; + svn_error_t *err = SVN_NO_ERROR; + + if ((handler == NULL) || (handler == Py_None)) + return SVN_NO_ERROR; + svn_swig_py_acquire_py_lock(); + + py_rev_props = svn_swig_py_prophash_to_dict(rev_props); + if (py_rev_props == NULL) + { + err = type_conversion_error("apr_hash_t *"); + goto error; + } + + py_prop_diffs = svn_swig_py_proparray_to_dict(prop_diffs); + + if (py_prop_diffs == NULL) + { + err = type_conversion_error("apr_array_header_t *"); + goto error; + } + + if ((result = PyObject_CallFunction(handler, + (char *)"slOOO&", + path, rev, py_rev_props, py_prop_diffs, + make_ob_pool, pool)) == NULL) + { + err = callback_exception_error(); + } + else + { + if (result != Py_None) + err = callback_bad_return_error("Not None"); + + /* FIXME: Support returned TxDeltaWindow object and + * set delta_handler and delta_baton */ + *delta_handler = NULL; + *delta_baton = NULL; + + Py_XDECREF(result); + } + +error: + + Py_XDECREF(py_rev_props); + Py_XDECREF(py_prop_diffs); + + svn_swig_py_release_py_lock(); + + return err; +} + + + Index: subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h =================================================================== --- subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h (revision 20114) +++ subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h (working copy) @@ -324,6 +324,16 @@ void *baton, apr_pool_t *pool); +SVN_SWIG_SWIGUTIL_EXPORT +svn_error_t *svn_swig_py_ra_file_rev_handler_func( + void *baton, + const char *path, + svn_revnum_t rev, + apr_hash_t *rev_props, + svn_txdelta_window_handler_t *delta_handler, + void **delta_baton, + apr_array_header_t *prop_diffs, + apr_pool_t *pool); #ifdef __cplusplus }