On Tuesday 23 March 2010 03:38:06 pm Роман Донченко wrote:
> Alexey Neyman <sti...@att.net> писал в своём письме Fri, 19 Mar 2010
>
> 02:26:28 +0300:
> > ...
> >
> > With stock 1.6.6, it produces the following traceback:
> >
> > ---------------------------------------------------------------------
> >---- svn: Commit blocked by pre-commit hook (exit code 1) with output:
> > Traceback (most recent call last):
> >   File "/tmp/c.repo/hooks/pre-commit", line 35, in <module>
> >     core.run_app(verify, sys.argv[1], sys.argv[2])
> >   File "/usr/local/lib/svn-python/svn/core.py", line 281, in run_app
> >     return func(application_pool, *args, **kw)
> >   File "/tmp/c.repo/hooks/pre-commit", line 31, in verify
> >     repos.svn_repos_replay2(txn_root, "", -1, True, e_ptr, e_baton,
> > None, pool)
> >   File "/usr/local/lib/svn-python/libsvn/repos.py", line 311, in
> > svn_repos_replay2
> >     return apply(_repos.svn_repos_replay2, args)
> >   File "/tmp/c.repo/hooks/pre-commit", line 22, in open_directory
> >     repos.svn_repos_history2(self.fs_ptr, path, history_lookup, None,
> > 0, self.base_rev, True, self.pool)
> >   File "/usr/local/lib/svn-python/libsvn/repos.py", line 407, in
> > svn_repos_history2
> >     return apply(_repos.svn_repos_history2, args)
> >   File "/tmp/c.repo/hooks/pre-commit", line 21, in history_lookup
> >     raise
> > core.SubversionException(apr_err=core.SVN_ERR_CEASE_INVOCATION,
> > message="Hi from history_lookup")
> > svn.core.SubversionException: ('Hi from history_lookup', 200021)
> > ---------------------------------------------------------------------
> >----
> >
> > Changed to the following code (difference from previous version is
> > that it
> > Py_DECREF's everything):
> >
> > ---------------------------------------------------------------------
> >---- static svn_error_t *callback_exception_error(void)
> > {
> >   PyObject *err = PyErr_Occurred();
> >   PyObject *svn_module = NULL, *exc_class = NULL;
> >   PyObject *message = NULL, *apr_err = NULL;
> >   svn_error_t *rv = NULL;
> >
> >   if ((svn_module = PyImport_ImportModule((char *)"svn.core")) ==
> > NULL) goto finished;
> >   if ((exc_class = PyObject_GetAttrString(svn_module,
> >         (char *)"SubversionException")) == NULL)
> >     goto finished;
> >   if (PyErr_GivenExceptionMatches(exc_class, err))
> >     {
> >       apr_err = PyObject_GetAttrString(err, (char *)"apr_err");
> >       message = PyObject_GetAttrString(err, (char *)"message");
> >       if (message && apr_err && PyString_Check(message) &&
> >           PyInt_Check(apr_err))
> >         rv = svn_error_create(PyInt_AsLong(apr_err), NULL,
> >             PyString_AsString(message));
> >     }
> > finished:
> >   Py_XDECREF(svn_module);
> >   Py_XDECREF(exc_class);
> >   Py_XDECREF(apr_err);
> >   Py_XDECREF(message);
> >   return rv ? rv : svn_error_create(SVN_ERR_SWIG_PY_EXCEPTION_SET,
> > NULL, "Python callback raised an exception"); }
> > ---------------------------------------------------------------------
> >----
> >
> > With this, pre-commit produces this traceback:
> >
> > ---------------------------------------------------------------------
> >---- svn: Commit blocked by pre-commit hook (exit code 1) with output:
> > Traceback (most recent call last):
> >   File "/tmp/c.repo/hooks/pre-commit", line 35, in <module>
> >     core.run_app(verify, sys.argv[1], sys.argv[2])
> >   File "/usr/local/lib/svn-python/svn/core.py", line 281, in run_app
> >     return func(application_pool, *args, **kw)
> >   File "/tmp/c.repo/hooks/pre-commit", line 31, in verify
> >     repos.svn_repos_replay2(txn_root, "", -1, True, e_ptr, e_baton,
> > None, pool)
> >   File "/usr/local/lib/svn-python/libsvn/repos.py", line 311, in
> > svn_repos_replay2
> >     return apply(_repos.svn_repos_replay2, args)
> > SystemError: NULL result without error in PyObject_Call
> > ---------------------------------------------------------------------
> >----
>
> OK, I think I got it. It couldn't find "apr_err", because
> PyErr_Occurred returns the exception _type_, and I'm pretty sure that
> the SystemError is due to not clearing the exception (although I don't
> know for sure, since I switched to PyErr_Fetch, and that automatically
> clears it). Please test with this version, which works for me:
>
> static svn_error_t *callback_exception_error(void)
> {
>    PyObject *svn_module = NULL, *svn_exc = NULL;
>    PyObject *message = NULL, *apr_err = NULL;
>    PyObject *exc, *exc_type, *exc_traceback;
>    svn_error_t *rv = NULL;
>
>    PyErr_Fetch(&exc_type, &exc, &exc_traceback);
>
>    if ((svn_module = PyImport_ImportModule("svn.core")) == NULL)
>      goto finished;
>    if ((svn_exc = PyObject_GetAttrString(svn_module,
> "SubversionException")) == NULL)
>      goto finished;
>
>    if (PyErr_GivenExceptionMatches(exc_type, svn_exc))
>      {
>        Py_DECREF(exc_type);
>        Py_DECREF(exc_traceback);
>      }
>    else
>      {
>        PyErr_Restore(exc_type, exc, exc_traceback);
>        goto finished;
>      }
>
>    if ((apr_err = PyObject_GetAttrString(exc, "apr_err")) == NULL)
>      goto finished;
>    if ((message = PyObject_GetAttrString(exc, "message")) == NULL)
>      goto finished;
>
>    Py_DECREF(exc);
>
>    /* A possible improvement here would be to convert the whole
>       SubversionException chain. */
>    if (PyString_Check(message) && PyInt_Check(apr_err))
>      rv = svn_error_create(PyInt_AsLong(apr_err), NULL,
>          PyString_AsString(message));
>
> finished:
>    Py_XDECREF(svn_module);
>    Py_XDECREF(svn_exc);
>    Py_XDECREF(apr_err);
>    Py_XDECREF(message);
>    return rv ? rv : svn_error_create(SVN_ERR_SWIG_PY_EXCEPTION_SET,
> NULL, "Python callback raised an exception"); }
> }

Works for me, thanks! I'll try to write a test case for 'make 
check-swig-py'.

Is this going to be checked to trunk only, or could it be checked in to 
upcoming 1.6.10 as well? I tried the same code with SVN I am currently 
using (1.6.6), it works as well.

Regards,
Alexey.

Reply via email to