1 /* Copyright © 2008 Jelmer Vernooij <jelmer@samba.org>
2 * -*- coding: utf-8 -*-
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <apr_general.h>
21 #include <svn_types.h>
24 #include <apr_file_io.h>
25 #include <apr_portable.h>
27 #include <structmember.h>
33 static PyObject *busy_exc;
35 PyAPI_DATA(PyTypeObject) Reporter_Type;
36 PyAPI_DATA(PyTypeObject) RemoteAccess_Type;
37 PyAPI_DATA(PyTypeObject) AuthProvider_Type;
38 PyAPI_DATA(PyTypeObject) CredentialsIter_Type;
39 PyAPI_DATA(PyTypeObject) TxDeltaWindowHandler_Type;
41 static svn_error_t *py_commit_callback(const svn_commit_info_t *commit_info, void *baton, apr_pool_t *pool)
43 PyObject *fn = (PyObject *)baton, *ret;
48 ret = PyObject_CallFunction(fn, "izz",
49 commit_info->revision, commit_info->date,
52 return py_svn_error();
57 static PyObject *pyify_lock(const svn_lock_t *lock)
59 return Py_BuildValue("(ssszbLL)",
60 lock->path, lock->token,
61 lock->owner, lock->comment,
64 lock->expiration_date);
67 static svn_error_t *py_lock_func (void *baton, const char *path, int do_lock,
68 const svn_lock_t *lock, svn_error_t *ra_err,
71 PyObject *py_ra_err = Py_None, *ret, *py_lock;
73 py_ra_err = PyErr_NewSubversionException(ra_err);
75 py_lock = pyify_lock(lock);
76 ret = PyObject_CallFunction((PyObject *)baton, "zbOO", path, do_lock,
81 return py_svn_error();
86 /** Connection to a remote Subversion repository. */
92 PyObject *progress_func;
95 PyObject *client_string_func;
96 PyObject *open_tmp_file_func;
102 const svn_ra_reporter2_t *reporter;
105 RemoteAccessObject *ra;
108 static PyObject *reporter_set_path(PyObject *self, PyObject *args)
111 svn_revnum_t revision;
113 char *lock_token = NULL;
114 ReporterObject *reporter = (ReporterObject *)self;
116 if (!PyArg_ParseTuple(args, "slb|z", &path, &revision, &start_empty,
120 if (!check_error(reporter->reporter->set_path(reporter->report_baton,
121 path, revision, start_empty,
122 lock_token, reporter->pool)))
128 static PyObject *reporter_delete_path(PyObject *self, PyObject *args)
130 ReporterObject *reporter = (ReporterObject *)self;
132 if (!PyArg_ParseTuple(args, "s", &path))
135 if (!check_error(reporter->reporter->delete_path(reporter->report_baton,
136 path, reporter->pool)))
142 static PyObject *reporter_link_path(PyObject *self, PyObject *args)
145 svn_revnum_t revision;
147 char *lock_token = NULL;
148 ReporterObject *reporter = (ReporterObject *)self;
150 if (!PyArg_ParseTuple(args, "sslb|z", &path, &url, &revision, &start_empty, &lock_token))
153 if (!check_error(reporter->reporter->link_path(reporter->report_baton, path, url,
154 revision, start_empty, lock_token, reporter->pool)))
160 static PyObject *reporter_finish(PyObject *self)
162 ReporterObject *reporter = (ReporterObject *)self;
164 reporter->ra->busy = false;
166 if (!check_error(reporter->reporter->finish_report(reporter->report_baton,
170 Py_XDECREF(reporter->ra);
175 static PyObject *reporter_abort(PyObject *self)
177 ReporterObject *reporter = (ReporterObject *)self;
179 reporter->ra->busy = false;
181 if (!check_error(reporter->reporter->abort_report(reporter->report_baton,
185 Py_XDECREF(reporter->ra);
190 static PyMethodDef reporter_methods[] = {
191 { "abort", (PyCFunction)reporter_abort, METH_NOARGS, NULL },
192 { "finish", (PyCFunction)reporter_finish, METH_NOARGS, NULL },
193 { "link_path", (PyCFunction)reporter_link_path, METH_VARARGS, NULL },
194 { "set_path", (PyCFunction)reporter_set_path, METH_VARARGS, NULL },
195 { "delete_path", (PyCFunction)reporter_delete_path, METH_VARARGS, NULL },
199 static void reporter_dealloc(PyObject *self)
201 ReporterObject *reporter = (ReporterObject *)self;
202 /* FIXME: Warn the user if abort_report/finish_report wasn't called? */
203 apr_pool_destroy(reporter->pool);
207 PyTypeObject Reporter_Type = {
208 PyObject_HEAD_INIT(NULL) 0,
209 "ra.Reporter", /* const char *tp_name; For printing, in format "<module>.<name>" */
210 sizeof(ReporterObject),
211 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
213 /* Methods to implement standard operations */
215 reporter_dealloc, /* destructor tp_dealloc; */
216 NULL, /* printfunc tp_print; */
217 NULL, /* getattrfunc tp_getattr; */
218 NULL, /* setattrfunc tp_setattr; */
219 NULL, /* cmpfunc tp_compare; */
220 NULL, /* reprfunc tp_repr; */
222 /* Method suites for standard classes */
224 NULL, /* PyNumberMethods *tp_as_number; */
225 NULL, /* PySequenceMethods *tp_as_sequence; */
226 NULL, /* PyMappingMethods *tp_as_mapping; */
228 /* More standard operations (here for binary compatibility) */
230 NULL, /* hashfunc tp_hash; */
231 NULL, /* ternaryfunc tp_call; */
232 NULL, /* reprfunc tp_str; */
233 NULL, /* getattrofunc tp_getattro; */
234 NULL, /* setattrofunc tp_setattro; */
236 /* Functions to access object as input/output buffer */
237 NULL, /* PyBufferProcs *tp_as_buffer; */
239 /* Flags to define presence of optional/expanded features */
240 0, /* long tp_flags; */
242 NULL, /* const char *tp_doc; Documentation string */
244 /* Assigned meaning in release 2.0 */
245 /* call function for all accessible objects */
246 NULL, /* traverseproc tp_traverse; */
248 /* delete references to contained objects */
249 NULL, /* inquiry tp_clear; */
251 /* Assigned meaning in release 2.1 */
252 /* rich comparisons */
253 NULL, /* richcmpfunc tp_richcompare; */
255 /* weak reference enabler */
256 0, /* Py_ssize_t tp_weaklistoffset; */
258 /* Added in release 2.2 */
260 NULL, /* getiterfunc tp_iter; */
261 NULL, /* iternextfunc tp_iternext; */
263 /* Attribute descriptor and subclassing stuff */
264 reporter_methods, /* struct PyMethodDef *tp_methods; */
269 * Get libsvn_ra version information.
271 * :return: tuple with major, minor, patch version number and tag.
273 static PyObject *version(PyObject *self)
275 const svn_version_t *ver = svn_ra_version();
276 return Py_BuildValue("(iiis)", ver->major, ver->minor,
277 ver->patch, ver->tag);
280 static svn_error_t *py_cb_editor_set_target_revision(void *edit_baton, svn_revnum_t target_revision, apr_pool_t *pool)
282 PyObject *self = (PyObject *)edit_baton, *ret;
284 ret = PyObject_CallMethod(self, "set_target_revision", "l", target_revision);
286 return py_svn_error();
291 static svn_error_t *py_cb_editor_open_root(void *edit_baton, svn_revnum_t base_revision, apr_pool_t *pool, void **root_baton)
293 PyObject *self = (PyObject *)edit_baton, *ret;
295 ret = PyObject_CallMethod(self, "open_root", "l", base_revision);
297 return py_svn_error();
298 *root_baton = (void *)ret;
302 static svn_error_t *py_cb_editor_delete_entry(const char *path, long revision, void *parent_baton, apr_pool_t *pool)
304 PyObject *self = (PyObject *)parent_baton, *ret;
305 ret = PyObject_CallMethod(self, "delete_entry", "sl", path, revision);
307 return py_svn_error();
312 static svn_error_t *py_cb_editor_add_directory(const char *path, void *parent_baton, const char *copyfrom_path, long copyfrom_revision, apr_pool_t *pool, void **child_baton)
314 PyObject *self = (PyObject *)parent_baton, *ret;
316 if (copyfrom_path == NULL) {
317 ret = PyObject_CallMethod(self, "add_directory", "s", path);
319 ret = PyObject_CallMethod(self, "add_directory", "ssl", path, copyfrom_path, copyfrom_revision);
322 return py_svn_error();
323 *child_baton = (void *)ret;
327 static svn_error_t *py_cb_editor_open_directory(const char *path, void *parent_baton, long base_revision, apr_pool_t *pool, void **child_baton)
329 PyObject *self = (PyObject *)parent_baton, *ret;
331 ret = PyObject_CallMethod(self, "open_directory", "sl", path, base_revision);
333 return py_svn_error();
334 *child_baton = (void *)ret;
338 static svn_error_t *py_cb_editor_change_prop(void *dir_baton, const char *name, const svn_string_t *value, apr_pool_t *pool)
340 PyObject *self = (PyObject *)dir_baton, *ret;
343 ret = PyObject_CallMethod(self, "change_prop", "sz#", name, value->data, value->len);
345 ret = PyObject_CallMethod(self, "change_prop", "sO", name, Py_None);
348 return py_svn_error();
353 static svn_error_t *py_cb_editor_close_directory(void *dir_baton, apr_pool_t *pool)
355 PyObject *self = (PyObject *)dir_baton, *ret;
356 ret = PyObject_CallMethod(self, "close", "");
359 return py_svn_error();
364 static svn_error_t *py_cb_editor_absent_directory(const char *path, void *parent_baton, apr_pool_t *pool)
366 PyObject *self = (PyObject *)parent_baton, *ret;
367 ret = PyObject_CallMethod(self, "absent_directory", "s", path);
369 return py_svn_error();
374 static svn_error_t *py_cb_editor_add_file(const char *path, void *parent_baton, const char *copy_path, long copy_revision, apr_pool_t *file_pool, void **file_baton)
376 PyObject *self = (PyObject *)parent_baton, *ret;
377 if (copy_path == NULL) {
378 ret = PyObject_CallMethod(self, "add_file", "s", path);
380 ret = PyObject_CallMethod(self, "add_file", "ssl", path, copy_path,
384 return py_svn_error();
385 *file_baton = (void *)ret;
389 static svn_error_t *py_cb_editor_open_file(const char *path, void *parent_baton, long base_revision, apr_pool_t *file_pool, void **file_baton)
391 PyObject *self = (PyObject *)parent_baton, *ret;
392 ret = PyObject_CallMethod(self, "open_file", "sl", path, base_revision);
394 return py_svn_error();
395 *file_baton = (void *)ret;
399 static svn_error_t *py_txdelta_window_handler(svn_txdelta_window_t *window, void *baton)
403 PyObject *fn = (PyObject *)baton, *py_new_data, *py_window;
405 /* User doesn't care about deltas */
409 if (window == NULL) {
411 Py_INCREF(py_window);
413 ops = PyList_New(window->num_ops);
416 for (i = 0; i < window->num_ops; i++) {
417 PyList_SetItem(ops, i, Py_BuildValue("(iII)", window->ops[i].action_code,
418 window->ops[i].offset,
419 window->ops[i].length));
421 if (window->new_data != NULL && window->new_data->data != NULL) {
422 py_new_data = PyString_FromStringAndSize(window->new_data->data, window->new_data->len);
424 py_new_data = Py_None;
426 py_window = Py_BuildValue("((LIIiOO))", window->sview_offset, window->sview_len, window->tview_len,
427 window->src_ops, ops, py_new_data);
429 Py_DECREF(py_new_data);
431 ret = PyObject_CallFunction(fn, "O", py_window);
432 Py_DECREF(py_window);
433 if (window == NULL) {
434 /* Signals all delta windows have been received */
438 return py_svn_error();
443 static svn_error_t *py_cb_editor_apply_textdelta(void *file_baton, const char *base_checksum, apr_pool_t *pool, svn_txdelta_window_handler_t *handler, void **handler_baton)
445 PyObject *self = (PyObject *)file_baton, *ret;
446 *handler_baton = NULL;
448 ret = PyObject_CallMethod(self, "apply_textdelta", "z", base_checksum);
450 return py_svn_error();
451 *handler_baton = (void *)ret;
452 *handler = py_txdelta_window_handler;
456 static svn_error_t *py_cb_editor_close_file(void *file_baton,
457 const char *text_checksum, apr_pool_t *pool)
459 PyObject *self = (PyObject *)file_baton, *ret;
461 if (text_checksum != NULL) {
462 ret = PyObject_CallMethod(self, "close", "");
464 ret = PyObject_CallMethod(self, "close", "s", text_checksum);
468 return py_svn_error();
473 static svn_error_t *py_cb_editor_absent_file(const char *path, void *parent_baton, apr_pool_t *pool)
475 PyObject *self = (PyObject *)parent_baton, *ret;
476 ret = PyObject_CallMethod(self, "absent_file", "s", path);
478 return py_svn_error();
483 static svn_error_t *py_cb_editor_close_edit(void *edit_baton, apr_pool_t *pool)
485 PyObject *self = (PyObject *)edit_baton, *ret;
486 ret = PyObject_CallMethod(self, "close", "");
489 return py_svn_error();
494 static svn_error_t *py_cb_editor_abort_edit(void *edit_baton, apr_pool_t *pool)
496 PyObject *self = (PyObject *)edit_baton, *ret;
497 ret = PyObject_CallMethod(self, "abort", "");
500 return py_svn_error();
505 static const svn_delta_editor_t py_editor = {
506 py_cb_editor_set_target_revision,
507 py_cb_editor_open_root,
508 py_cb_editor_delete_entry,
509 py_cb_editor_add_directory,
510 py_cb_editor_open_directory,
511 py_cb_editor_change_prop,
512 py_cb_editor_close_directory,
513 py_cb_editor_absent_directory,
514 py_cb_editor_add_file,
515 py_cb_editor_open_file,
516 py_cb_editor_apply_textdelta,
517 py_cb_editor_change_prop,
518 py_cb_editor_close_file,
519 py_cb_editor_absent_file,
520 py_cb_editor_close_edit,
521 py_cb_editor_abort_edit
524 static svn_error_t *py_file_rev_handler(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)
526 PyObject *fn = (PyObject *)baton, *ret, *py_rev_props;
528 py_rev_props = prop_hash_to_dict(rev_props);
529 if (py_rev_props == NULL)
530 return py_svn_error();
532 ret = PyObject_CallFunction(fn, "slO", path, rev, py_rev_props);
533 Py_DECREF(py_rev_props);
535 return py_svn_error();
537 *delta_baton = (void *)ret;
538 *delta_handler = py_txdelta_window_handler;
543 static void ra_done_handler(void *_ra)
545 RemoteAccessObject *ra = (RemoteAccessObject *)_ra;
552 #define RUN_RA_WITH_POOL(pool, ra, cmd) \
553 if (!check_error((cmd))) { \
554 apr_pool_destroy(pool); \
560 static bool ra_check_busy(RemoteAccessObject *raobj)
563 PyErr_SetString(busy_exc, "Remote access object already in use");
570 #if SVN_VER_MAJOR >= 1 && SVN_VER_MINOR >= 5
571 static svn_error_t *py_get_client_string(void *baton, const char **name, apr_pool_t *pool)
573 RemoteAccessObject *self = (RemoteAccessObject *)baton;
576 if (self->client_string_func == Py_None) {
581 ret = PyObject_CallFunction(self->client_string_func, "");
584 return py_svn_error();
586 *name = apr_pstrdup(pool, PyString_AsString(ret));
593 /* Based on svn_swig_py_make_file() from Subversion */
594 static svn_error_t *py_open_tmp_file(apr_file_t **fp, void *callback,
597 RemoteAccessObject *self = (RemoteAccessObject *)callback;
601 if (self->open_tmp_file_func == Py_None) {
604 SVN_ERR (svn_io_temp_dir (&path, pool));
605 path = svn_path_join (path, "tempfile", pool);
606 SVN_ERR (svn_io_open_unique_file (fp, NULL, path, ".tmp", TRUE, pool));
611 ret = PyObject_CallFunction(self->open_tmp_file_func, "");
614 return py_svn_error();
616 if (PyString_Check(ret)) {
617 char* fname = PyString_AsString(ret);
618 status = apr_file_open(fp, fname, APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT,
621 PyErr_SetAprStatus(status);
626 } else if (PyFile_Check(ret)) {
628 apr_os_file_t osfile;
630 file = PyFile_AsFile(ret);
632 osfile = (apr_os_file_t)_get_osfhandle(_fileno(file));
634 osfile = (apr_os_file_t)fileno(file);
636 status = apr_os_file_put(fp, &osfile, O_CREAT | O_WRONLY, pool);
638 PyErr_SetAprStatus(status);
643 PyErr_SetString(PyExc_TypeError, "Unknown type for file variable");
651 static void py_progress_func(apr_off_t progress, apr_off_t total, void *baton, apr_pool_t *pool)
653 RemoteAccessObject *ra = (RemoteAccessObject *)baton;
654 PyObject *fn = (PyObject *)ra->progress_func, *ret;
658 ret = PyObject_CallFunction(fn, "ll", progress, total);
659 /* TODO: What to do with exceptions raised here ? */
663 static PyObject *ra_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
665 char *kwnames[] = { "url", "progress_cb", "auth", "config", "client_string_func",
666 "open_tmp_file_func", NULL };
668 PyObject *progress_cb = Py_None;
669 AuthObject *auth = (AuthObject *)Py_None;
670 PyObject *config = Py_None;
671 PyObject *client_string_func = Py_None, *open_tmp_file_func = Py_None;
672 RemoteAccessObject *ret;
673 apr_hash_t *config_hash;
674 svn_ra_callbacks2_t *callbacks2;
675 svn_auth_baton_t *auth_baton;
677 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOOOO", kwnames, &url, &progress_cb,
678 (PyObject **)&auth, &config, &client_string_func,
679 &open_tmp_file_func))
682 ret = PyObject_New(RemoteAccessObject, &RemoteAccess_Type);
686 if ((PyObject *)auth == Py_None) {
690 /* FIXME: check auth is an instance of Auth_Type */
693 auth_baton = ret->auth->auth_baton;
697 ret->pool = Pool(NULL);
698 if (ret->pool == NULL)
700 ret->url = apr_pstrdup(ret->pool, url);
701 if (!check_error(svn_ra_create_callbacks(&callbacks2, ret->pool))) {
702 apr_pool_destroy(ret->pool);
707 ret->client_string_func = client_string_func;
708 ret->open_tmp_file_func = open_tmp_file_func;
709 Py_INCREF(client_string_func);
710 callbacks2->progress_func = py_progress_func;
711 callbacks2->auth_baton = auth_baton;
712 callbacks2->open_tmp_file = py_open_tmp_file;
713 ret->progress_func = progress_cb;
714 callbacks2->progress_baton = (void *)ret;
715 #if SVN_VER_MAJOR >= 1 && SVN_VER_MINOR >= 5
716 callbacks2->get_client_string = py_get_client_string;
719 config_hash = config_hash_from_object(config, ret->pool);
720 if (config_hash == NULL) {
721 apr_pool_destroy(ret->pool);
725 if (!check_error(svn_ra_open2(&ret->ra, apr_pstrdup(ret->pool, url),
726 callbacks2, ret, config_hash, ret->pool))) {
727 apr_pool_destroy(ret->pool);
732 return (PyObject *)ret;
736 * Obtain the globally unique identifier for this repository.
738 static PyObject *ra_get_uuid(PyObject *self)
741 RemoteAccessObject *ra = (RemoteAccessObject *)self;
743 apr_pool_t *temp_pool;
745 if (ra_check_busy(ra))
748 temp_pool = Pool(NULL);
749 if (temp_pool == NULL)
751 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_get_uuid(ra->ra, &uuid, temp_pool));
752 ret = PyString_FromString(uuid);
753 apr_pool_destroy(temp_pool);
757 /** Switch to a different url. */
758 static PyObject *ra_reparent(PyObject *self, PyObject *args)
761 apr_pool_t *temp_pool;
762 RemoteAccessObject *ra = (RemoteAccessObject *)self;
764 if (!PyArg_ParseTuple(args, "s", &url))
767 if (ra_check_busy(ra))
770 temp_pool = Pool(NULL);
771 if (temp_pool == NULL)
773 ra->url = svn_path_canonicalize(url, ra->pool);
774 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_reparent(ra->ra, ra->url, temp_pool));
775 apr_pool_destroy(temp_pool);
780 * Obtain the number of the latest committed revision in the
781 * connected repository.
783 static PyObject *ra_get_latest_revnum(PyObject *self)
785 RemoteAccessObject *ra = (RemoteAccessObject *)self;
786 svn_revnum_t latest_revnum;
787 apr_pool_t *temp_pool;
788 if (ra_check_busy(ra))
791 temp_pool = Pool(NULL);
792 if (temp_pool == NULL)
794 RUN_RA_WITH_POOL(temp_pool, ra,
795 svn_ra_get_latest_revnum(ra->ra, &latest_revnum, temp_pool));
796 apr_pool_destroy(temp_pool);
797 return PyInt_FromLong(latest_revnum);
800 static PyObject *ra_get_log(PyObject *self, PyObject *args, PyObject *kwargs)
802 char *kwnames[] = { "callback", "paths", "start", "end", "limit",
803 "discover_changed_paths", "strict_node_history", "include_merged_revisions", "revprops", NULL };
804 PyObject *callback, *paths;
805 svn_revnum_t start = 0, end = 0;
807 bool discover_changed_paths=false, strict_node_history=true,include_merged_revisions=false;
808 RemoteAccessObject *ra = (RemoteAccessObject *)self;
809 PyObject *revprops = Py_None;
810 apr_pool_t *temp_pool;
811 apr_array_header_t *apr_paths;
812 apr_array_header_t *apr_revprops;
814 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOll|ibbbO:get_log", kwnames,
815 &callback, &paths, &start, &end, &limit,
816 &discover_changed_paths, &strict_node_history,
817 &include_merged_revisions, &revprops))
820 if (ra_check_busy(ra))
823 temp_pool = Pool(NULL);
824 if (temp_pool == NULL)
826 if (paths == Py_None) {
827 /* FIXME: The subversion libraries don't behave as expected,
828 * so tweak our own parameters a bit. */
829 apr_paths = apr_array_make(temp_pool, 1, sizeof(char *));
830 APR_ARRAY_PUSH(apr_paths, char *) = apr_pstrdup(temp_pool, "");
832 } else if (!string_list_to_apr_array(temp_pool, paths, &apr_paths)) {
833 apr_pool_destroy(temp_pool);
837 #if SVN_VER_MAJOR <= 1 && SVN_VER_MINOR < 5
838 if (revprops == Py_None) {
839 PyErr_SetString(PyExc_NotImplementedError, "fetching all revision properties not supported");
840 apr_pool_destroy(temp_pool);
842 } else if (!PyList_Check(revprops)) {
843 PyErr_SetString(PyExc_TypeError, "revprops should be a list");
844 apr_pool_destroy(temp_pool);
848 for (i = 0; i < PyList_Size(revprops); i++) {
849 const char *n = PyString_AsString(PyList_GetItem(revprops, i));
850 if (strcmp(SVN_PROP_REVISION_LOG, n) &&
851 strcmp(SVN_PROP_REVISION_AUTHOR, n) &&
852 strcmp(SVN_PROP_REVISION_DATE, n)) {
853 PyErr_SetString(PyExc_NotImplementedError,
854 "fetching custom revision properties not supported");
855 apr_pool_destroy(temp_pool);
861 if (include_merged_revisions) {
862 PyErr_SetString(PyExc_NotImplementedError, "include_merged_revisions not supported in Subversion 1.4");
863 apr_pool_destroy(temp_pool);
868 if (!string_list_to_apr_array(temp_pool, revprops, &apr_revprops)) {
869 apr_pool_destroy(temp_pool);
873 #if SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 5
874 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_get_log2(ra->ra,
875 apr_paths, start, end, limit,
876 discover_changed_paths, strict_node_history,
877 include_merged_revisions,
879 py_svn_log_entry_receiver,
880 callback, temp_pool));
882 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_get_log(ra->ra,
883 apr_paths, start, end, limit,
884 discover_changed_paths, strict_node_history, py_svn_log_wrapper,
885 callback, temp_pool));
887 apr_pool_destroy(temp_pool);
892 * Obtain the URL of the root of this repository.
894 static PyObject *ra_get_repos_root(PyObject *self)
896 RemoteAccessObject *ra = (RemoteAccessObject *)self;
898 apr_pool_t *temp_pool;
900 if (ra->root == NULL) {
901 if (ra_check_busy(ra))
904 temp_pool = Pool(NULL);
905 if (temp_pool == NULL)
907 RUN_RA_WITH_POOL(temp_pool, ra,
908 svn_ra_get_repos_root(ra->ra, &root, temp_pool));
909 ra->root = apr_pstrdup(ra->pool, root);
910 apr_pool_destroy(temp_pool);
913 return PyString_FromString(ra->root);
916 static PyObject *ra_do_update(PyObject *self, PyObject *args)
918 svn_revnum_t revision_to_update_to;
921 PyObject *update_editor;
922 const svn_ra_reporter2_t *reporter;
924 apr_pool_t *temp_pool;
926 RemoteAccessObject *ra = (RemoteAccessObject *)self;
928 if (!PyArg_ParseTuple(args, "lsbO:do_update", &revision_to_update_to, &update_target, &recurse, &update_editor))
931 if (ra_check_busy(ra))
934 temp_pool = Pool(NULL);
935 if (temp_pool == NULL)
938 Py_INCREF(update_editor);
939 if (!check_error(svn_ra_do_update(ra->ra, &reporter,
941 revision_to_update_to,
942 update_target, recurse,
943 &py_editor, update_editor,
945 apr_pool_destroy(temp_pool);
949 ret = PyObject_New(ReporterObject, &Reporter_Type);
952 ret->reporter = reporter;
953 ret->report_baton = report_baton;
954 ret->pool = temp_pool;
957 return (PyObject *)ret;
960 static PyObject *ra_do_switch(PyObject *self, PyObject *args)
962 RemoteAccessObject *ra = (RemoteAccessObject *)self;
963 svn_revnum_t revision_to_update_to;
967 PyObject *update_editor;
968 const svn_ra_reporter2_t *reporter;
970 apr_pool_t *temp_pool;
973 if (!PyArg_ParseTuple(args, "lsbsO:do_switch", &revision_to_update_to, &update_target,
974 &recurse, &switch_url, &update_editor))
976 if (ra_check_busy(ra))
979 temp_pool = Pool(NULL);
980 if (temp_pool == NULL)
982 Py_INCREF(update_editor);
983 if (!check_error(svn_ra_do_switch(
984 ra->ra, &reporter, &report_baton,
985 revision_to_update_to, update_target,
986 recurse, switch_url, &py_editor,
987 update_editor, temp_pool))) {
988 apr_pool_destroy(temp_pool);
992 ret = PyObject_New(ReporterObject, &Reporter_Type);
995 ret->reporter = reporter;
996 ret->report_baton = report_baton;
997 ret->pool = temp_pool;
1000 return (PyObject *)ret;
1003 static PyObject *ra_replay(PyObject *self, PyObject *args)
1005 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1006 apr_pool_t *temp_pool;
1007 svn_revnum_t revision, low_water_mark;
1008 PyObject *update_editor;
1009 bool send_deltas = true;
1011 if (!PyArg_ParseTuple(args, "llO|b", &revision, &low_water_mark, &update_editor, &send_deltas))
1014 if (ra_check_busy(ra))
1017 temp_pool = Pool(NULL);
1018 if (temp_pool == NULL)
1020 Py_INCREF(update_editor);
1021 RUN_RA_WITH_POOL(temp_pool, ra,
1022 svn_ra_replay(ra->ra, revision, low_water_mark,
1023 send_deltas, &py_editor, update_editor,
1025 apr_pool_destroy(temp_pool);
1030 static svn_error_t *py_revstart_cb(svn_revnum_t revision, void *replay_baton,
1031 const svn_delta_editor_t **editor, void **edit_baton, apr_hash_t *rev_props, apr_pool_t *pool)
1033 PyObject *cbs = (PyObject *)replay_baton;
1034 PyObject *py_start_fn = PyTuple_GetItem(cbs, 0);
1035 PyObject *py_revprops = prop_hash_to_dict(rev_props);
1038 ret = PyObject_CallFunction(py_start_fn, "lO", revision, py_revprops);
1040 return py_svn_error();
1042 *editor = &py_editor;
1048 static svn_error_t *py_revfinish_cb(svn_revnum_t revision, void *replay_baton,
1049 const svn_delta_editor_t *editor, void *edit_baton,
1050 apr_hash_t *rev_props, apr_pool_t *pool)
1052 PyObject *cbs = (PyObject *)replay_baton;
1053 PyObject *py_finish_fn = PyTuple_GetItem(cbs, 1);
1054 PyObject *py_revprops = prop_hash_to_dict(rev_props);
1057 ret = PyObject_CallFunction(py_finish_fn, "lOO", revision, py_revprops, edit_baton);
1059 return py_svn_error();
1061 Py_DECREF((PyObject *)edit_baton);
1067 static PyObject *ra_replay_range(PyObject *self, PyObject *args)
1069 #if SVN_VER_MAJOR >= 1 && SVN_VER_MINOR >= 5
1070 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1071 apr_pool_t *temp_pool;
1072 svn_revnum_t start_revision, end_revision, low_water_mark;
1074 bool send_deltas = true;
1076 if (!PyArg_ParseTuple(args, "lllO|b", &start_revision, &end_revision, &low_water_mark, &cbs, &send_deltas))
1079 if (!PyTuple_Check(cbs)) {
1080 PyErr_SetString(PyExc_TypeError, "Expected tuple with callbacks");
1084 if (ra_check_busy(ra))
1087 temp_pool = Pool(NULL);
1088 if (temp_pool == NULL)
1092 RUN_RA_WITH_POOL(temp_pool, ra,
1093 svn_ra_replay_range(ra->ra, start_revision, end_revision, low_water_mark,
1094 send_deltas, py_revstart_cb, py_revfinish_cb, cbs,
1096 apr_pool_destroy(temp_pool);
1100 PyErr_SetString(PyExc_NotImplementedError, "svn_ra_replay not available with Subversion 1.4");
1107 static PyObject *ra_rev_proplist(PyObject *self, PyObject *args)
1109 apr_pool_t *temp_pool;
1111 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1114 if (!PyArg_ParseTuple(args, "l", &rev))
1117 if (ra_check_busy(ra))
1120 temp_pool = Pool(NULL);
1121 if (temp_pool == NULL)
1123 RUN_RA_WITH_POOL(temp_pool, ra,
1124 svn_ra_rev_proplist(ra->ra, rev, &props, temp_pool));
1125 py_props = prop_hash_to_dict(props);
1126 apr_pool_destroy(temp_pool);
1130 static PyObject *get_commit_editor(PyObject *self, PyObject *args, PyObject *kwargs)
1132 char *kwnames[] = { "revprops", "callback", "lock_tokens", "keep_locks",
1134 PyObject *revprops, *commit_callback = Py_None, *lock_tokens = Py_None;
1135 bool keep_locks = false;
1137 const svn_delta_editor_t *editor;
1139 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1140 apr_hash_t *hash_lock_tokens;
1142 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOb", kwnames, &revprops, &commit_callback, &lock_tokens, &keep_locks))
1148 if (lock_tokens == Py_None) {
1149 hash_lock_tokens = NULL;
1153 hash_lock_tokens = apr_hash_make(pool);
1154 while (PyDict_Next(lock_tokens, &idx, &k, &v)) {
1155 apr_hash_set(hash_lock_tokens, PyString_AsString(k),
1156 PyString_Size(k), PyString_AsString(v));
1160 if (!PyDict_Check(revprops)) {
1161 apr_pool_destroy(pool);
1162 PyErr_SetString(PyExc_TypeError, "Expected dictionary with revision properties");
1166 if (ra_check_busy(ra))
1169 if (!check_error(svn_ra_get_commit_editor2(ra->ra, &editor,
1171 PyString_AsString(PyDict_GetItemString(revprops, SVN_PROP_REVISION_LOG)), py_commit_callback,
1172 commit_callback, hash_lock_tokens, keep_locks, pool))) {
1173 apr_pool_destroy(pool);
1179 return new_editor_object(editor, edit_baton, pool,
1180 &Editor_Type, ra_done_handler, ra);
1183 static PyObject *ra_change_rev_prop(PyObject *self, PyObject *args)
1187 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1190 apr_pool_t *temp_pool;
1191 svn_string_t *val_string;
1193 if (!PyArg_ParseTuple(args, "lss#", &rev, &name, &value, &vallen))
1195 if (ra_check_busy(ra))
1198 temp_pool = Pool(NULL);
1199 if (temp_pool == NULL)
1201 val_string = svn_string_ncreate(value, vallen, temp_pool);
1202 RUN_RA_WITH_POOL(temp_pool, ra,
1203 svn_ra_change_rev_prop(ra->ra, rev, name, val_string,
1205 apr_pool_destroy(temp_pool);
1209 static PyObject *ra_get_dir(PyObject *self, PyObject *args)
1211 apr_pool_t *temp_pool;
1212 apr_hash_t *dirents;
1213 apr_hash_index_t *idx;
1215 svn_revnum_t fetch_rev;
1217 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1218 svn_dirent_t *dirent;
1221 svn_revnum_t revision = -1;
1222 int dirent_fields = 0;
1223 PyObject *py_dirents, *py_props;
1225 if (!PyArg_ParseTuple(args, "s|li", &path, &revision, &dirent_fields))
1228 if (ra_check_busy(ra))
1231 temp_pool = Pool(NULL);
1232 if (temp_pool == NULL)
1235 if (revision != SVN_INVALID_REVNUM)
1236 fetch_rev = revision;
1238 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_get_dir2(ra->ra, &dirents, &fetch_rev, &props,
1239 path, revision, dirent_fields, temp_pool));
1241 if (dirents == NULL) {
1242 py_dirents = Py_None;
1244 py_dirents = PyDict_New();
1245 idx = apr_hash_first(temp_pool, dirents);
1246 while (idx != NULL) {
1247 PyObject *py_dirent;
1248 apr_hash_this(idx, (const void **)&key, &klen, (void **)&dirent);
1249 py_dirent = PyDict_New();
1250 if (dirent_fields & 0x1)
1251 PyDict_SetItemString(py_dirent, "kind",
1252 PyInt_FromLong(dirent->kind));
1253 if (dirent_fields & 0x2)
1254 PyDict_SetItemString(py_dirent, "size",
1255 PyLong_FromLong(dirent->size));
1256 if (dirent_fields & 0x4)
1257 PyDict_SetItemString(py_dirent, "has_props",
1258 PyBool_FromLong(dirent->has_props));
1259 if (dirent_fields & 0x8)
1260 PyDict_SetItemString(py_dirent, "created_rev",
1261 PyLong_FromLong(dirent->created_rev));
1262 if (dirent_fields & 0x10)
1263 PyDict_SetItemString(py_dirent, "time",
1264 PyLong_FromLong(dirent->time));
1265 if (dirent_fields & 0x20)
1266 PyDict_SetItemString(py_dirent, "last_author",
1267 PyString_FromString(dirent->last_author));
1268 PyDict_SetItemString(py_dirents, key, py_dirent);
1269 idx = apr_hash_next(idx);
1273 py_props = prop_hash_to_dict(props);
1274 if (py_props == NULL) {
1275 apr_pool_destroy(temp_pool);
1278 apr_pool_destroy(temp_pool);
1279 return Py_BuildValue("(NlN)", py_dirents, fetch_rev, py_props);
1282 static PyObject *ra_get_file(PyObject *self, PyObject *args)
1285 svn_revnum_t revision = -1;
1286 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1288 svn_revnum_t fetch_rev;
1289 PyObject *py_stream, *py_props;
1290 apr_pool_t *temp_pool;
1292 if (!PyArg_ParseTuple(args, "sO|l", &path, &py_stream, &revision))
1295 if (ra_check_busy(ra))
1298 temp_pool = Pool(NULL);
1299 if (temp_pool == NULL)
1302 if (revision != SVN_INVALID_REVNUM)
1303 fetch_rev = revision;
1305 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_get_file(ra->ra, path, revision,
1306 new_py_stream(temp_pool, py_stream),
1307 &fetch_rev, &props, temp_pool));
1309 py_props = prop_hash_to_dict(props);
1310 if (py_props == NULL) {
1311 apr_pool_destroy(temp_pool);
1315 apr_pool_destroy(temp_pool);
1317 return Py_BuildValue("(lN)", fetch_rev, py_props);
1320 static PyObject *ra_get_lock(PyObject *self, PyObject *args)
1323 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1325 apr_pool_t *temp_pool;
1327 if (!PyArg_ParseTuple(args, "s", &path))
1330 if (ra_check_busy(ra))
1333 temp_pool = Pool(NULL);
1334 if (temp_pool == NULL)
1336 RUN_RA_WITH_POOL(temp_pool, ra,
1337 svn_ra_get_lock(ra->ra, &lock, path, temp_pool));
1338 apr_pool_destroy(temp_pool);
1339 return wrap_lock(lock);
1342 static PyObject *ra_check_path(PyObject *self, PyObject *args)
1345 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1346 svn_revnum_t revision;
1347 svn_node_kind_t kind;
1348 apr_pool_t *temp_pool;
1350 if (!PyArg_ParseTuple(args, "sl", &path, &revision))
1352 if (ra_check_busy(ra))
1355 temp_pool = Pool(NULL);
1356 if (temp_pool == NULL)
1358 RUN_RA_WITH_POOL(temp_pool, ra,
1359 svn_ra_check_path(ra->ra, path, revision, &kind,
1361 apr_pool_destroy(temp_pool);
1362 return PyInt_FromLong(kind);
1365 static PyObject *ra_has_capability(PyObject *self, PyObject *args)
1367 #if SVN_VER_MAJOR >= 1 && SVN_VER_MINOR >= 5
1369 apr_pool_t *temp_pool;
1370 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1373 if (!PyArg_ParseTuple(args, "s", &capability))
1376 if (ra_check_busy(ra))
1379 temp_pool = Pool(NULL);
1380 if (temp_pool == NULL)
1382 RUN_RA_WITH_POOL(temp_pool, ra,
1383 svn_ra_has_capability(ra->ra, &has, capability, temp_pool));
1384 apr_pool_destroy(temp_pool);
1385 return PyBool_FromLong(has);
1387 PyErr_SetString(PyExc_NotImplementedError, "has_capability is only supported in Subversion >= 1.5");
1392 static PyObject *ra_unlock(PyObject *self, PyObject *args)
1394 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1395 PyObject *path_tokens, *lock_func, *k, *v;
1398 apr_pool_t *temp_pool;
1399 apr_hash_t *hash_path_tokens;
1401 if (!PyArg_ParseTuple(args, "ObO", &path_tokens, &break_lock, &lock_func))
1404 if (ra_check_busy(ra))
1407 temp_pool = Pool(NULL);
1408 if (temp_pool == NULL)
1410 hash_path_tokens = apr_hash_make(temp_pool);
1411 while (PyDict_Next(path_tokens, &idx, &k, &v)) {
1412 apr_hash_set(hash_path_tokens, PyString_AsString(k), PyString_Size(k), (char *)PyString_AsString(v));
1414 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_unlock(ra->ra, hash_path_tokens, break_lock,
1415 py_lock_func, lock_func, temp_pool));
1417 apr_pool_destroy(temp_pool);
1421 static PyObject *ra_lock(PyObject *self, PyObject *args)
1423 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1424 PyObject *path_revs;
1427 PyObject *lock_func, *k, *v;
1428 apr_pool_t *temp_pool;
1429 apr_hash_t *hash_path_revs;
1433 if (!PyArg_ParseTuple(args, "OsbO", &path_revs, &comment, &steal_lock,
1437 if (ra_check_busy(ra))
1440 temp_pool = Pool(NULL);
1441 if (temp_pool == NULL)
1443 if (path_revs == Py_None) {
1444 hash_path_revs = NULL;
1446 hash_path_revs = apr_hash_make(temp_pool);
1449 while (PyDict_Next(path_revs, &idx, &k, &v)) {
1450 rev = (svn_revnum_t *)apr_palloc(temp_pool, sizeof(svn_revnum_t));
1451 *rev = PyLong_AsLong(v);
1452 apr_hash_set(hash_path_revs, PyString_AsString(k), PyString_Size(k),
1453 PyString_AsString(v));
1455 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_lock(ra->ra, hash_path_revs, comment, steal_lock,
1456 py_lock_func, lock_func, temp_pool));
1457 apr_pool_destroy(temp_pool);
1461 static PyObject *ra_get_locks(PyObject *self, PyObject *args)
1464 apr_pool_t *temp_pool;
1465 apr_hash_t *hash_locks;
1466 apr_hash_index_t *idx;
1467 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1473 if (!PyArg_ParseTuple(args, "s", &path))
1476 if (ra_check_busy(ra))
1479 temp_pool = Pool(NULL);
1480 if (temp_pool == NULL)
1482 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_get_locks(ra->ra, &hash_locks, path, temp_pool));
1485 for (idx = apr_hash_first(temp_pool, hash_locks); idx != NULL;
1486 idx = apr_hash_next(idx)) {
1487 apr_hash_this(idx, (const void **)&key, &klen, (void **)&lock);
1488 PyDict_SetItemString(ret, key, pyify_lock(lock));
1491 apr_pool_destroy(temp_pool);
1495 static PyObject *ra_get_locations(PyObject *self, PyObject *args)
1498 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1499 svn_revnum_t peg_revision;
1500 PyObject *location_revisions;
1501 apr_pool_t *temp_pool;
1502 apr_hash_t *hash_locations;
1503 apr_hash_index_t *idx;
1509 if (!PyArg_ParseTuple(args, "slO", &path, &peg_revision, &location_revisions))
1512 if (ra_check_busy(ra))
1515 temp_pool = Pool(NULL);
1516 if (temp_pool == NULL)
1518 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_get_locations(ra->ra, &hash_locations,
1520 revnum_list_to_apr_array(temp_pool, location_revisions),
1524 for (idx = apr_hash_first(temp_pool, hash_locations); idx != NULL;
1525 idx = apr_hash_next(idx)) {
1526 apr_hash_this(idx, (const void **)&key, &klen, (void **)&val);
1527 PyDict_SetItem(ret, PyInt_FromLong(*key), PyString_FromString(val));
1529 apr_pool_destroy(temp_pool);
1533 static PyObject *ra_get_file_revs(PyObject *self, PyObject *args)
1536 svn_revnum_t start, end;
1537 PyObject *file_rev_handler;
1538 apr_pool_t *temp_pool;
1539 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1541 if (!PyArg_ParseTuple(args, "sllO", &path, &start, &end, &file_rev_handler))
1544 if (ra_check_busy(ra))
1547 temp_pool = Pool(NULL);
1548 if (temp_pool == NULL)
1551 RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_get_file_revs(ra->ra, path, start, end,
1552 py_file_rev_handler, (void *)file_rev_handler,
1555 apr_pool_destroy(temp_pool);
1560 static void ra_dealloc(PyObject *self)
1562 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1563 Py_XDECREF(ra->progress_func);
1564 apr_pool_destroy(ra->pool);
1565 Py_XDECREF(ra->auth);
1569 static PyObject *ra_repr(PyObject *self)
1571 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1572 return PyString_FromFormat("RemoteAccess(%s)", ra->url);
1575 static int ra_set_progress_func(PyObject *self, PyObject *value, void *closure)
1577 RemoteAccessObject *ra = (RemoteAccessObject *)self;
1578 Py_XDECREF(ra->progress_func);
1579 ra->progress_func = value;
1580 Py_INCREF(ra->progress_func);
1584 static PyGetSetDef ra_getsetters[] = {
1585 { "progress_func", NULL, ra_set_progress_func, NULL },
1589 static PyMethodDef ra_methods[] = {
1590 { "get_file_revs", ra_get_file_revs, METH_VARARGS, NULL },
1591 { "get_locations", ra_get_locations, METH_VARARGS, NULL },
1592 { "get_locks", ra_get_locks, METH_VARARGS, NULL },
1593 { "lock", ra_lock, METH_VARARGS, NULL },
1594 { "unlock", ra_unlock, METH_VARARGS, NULL },
1595 { "has_capability", ra_has_capability, METH_VARARGS, NULL },
1596 { "check_path", ra_check_path, METH_VARARGS, NULL },
1597 { "get_lock", ra_get_lock, METH_VARARGS, NULL },
1598 { "get_dir", ra_get_dir, METH_VARARGS, NULL },
1599 { "get_file", ra_get_file, METH_VARARGS, NULL },
1600 { "change_rev_prop", ra_change_rev_prop, METH_VARARGS, NULL },
1601 { "get_commit_editor", (PyCFunction)get_commit_editor, METH_VARARGS|METH_KEYWORDS, NULL },
1602 { "rev_proplist", ra_rev_proplist, METH_VARARGS, NULL },
1603 { "replay", ra_replay, METH_VARARGS, NULL },
1604 { "replay_range", ra_replay_range, METH_VARARGS, NULL },
1605 { "do_switch", ra_do_switch, METH_VARARGS, NULL },
1606 { "do_update", ra_do_update, METH_VARARGS, NULL },
1607 { "get_repos_root", (PyCFunction)ra_get_repos_root, METH_VARARGS|METH_NOARGS, NULL },
1608 { "get_log", (PyCFunction)ra_get_log, METH_VARARGS|METH_KEYWORDS, NULL },
1609 { "get_latest_revnum", (PyCFunction)ra_get_latest_revnum, METH_NOARGS, NULL },
1610 { "reparent", ra_reparent, METH_VARARGS, NULL },
1611 { "get_uuid", (PyCFunction)ra_get_uuid, METH_NOARGS, NULL },
1615 static PyMemberDef ra_members[] = {
1616 { "busy", T_BYTE, offsetof(RemoteAccessObject, busy), READONLY, NULL },
1617 { "url", T_STRING, offsetof(RemoteAccessObject, url), READONLY, NULL },
1621 PyTypeObject RemoteAccess_Type = {
1622 PyObject_HEAD_INIT(NULL) 0,
1623 "ra.RemoteAccess", /* const char *tp_name; For printing, in format "<module>.<name>" */
1624 sizeof(RemoteAccessObject),
1625 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
1627 /* Methods to implement standard operations */
1629 ra_dealloc, /* destructor tp_dealloc; */
1630 NULL, /* printfunc tp_print; */
1631 NULL, /* getattrfunc tp_getattr; */
1632 NULL, /* setattrfunc tp_setattr; */
1633 NULL, /* cmpfunc tp_compare; */
1634 ra_repr, /* reprfunc tp_repr; */
1636 /* Method suites for standard classes */
1638 NULL, /* PyNumberMethods *tp_as_number; */
1639 NULL, /* PySequenceMethods *tp_as_sequence; */
1640 NULL, /* PyMappingMethods *tp_as_mapping; */
1642 /* More standard operations (here for binary compatibility) */
1644 NULL, /* hashfunc tp_hash; */
1645 NULL, /* ternaryfunc tp_call; */
1646 NULL, /* reprfunc tp_str; */
1647 NULL, /* getattrofunc tp_getattro; */
1648 NULL, /* setattrofunc tp_setattro; */
1650 /* Functions to access object as input/output buffer */
1651 NULL, /* PyBufferProcs *tp_as_buffer; */
1653 /* Flags to define presence of optional/expanded features */
1654 0, /* long tp_flags; */
1656 NULL, /* const char *tp_doc; Documentation string */
1658 /* Assigned meaning in release 2.0 */
1659 /* call function for all accessible objects */
1660 NULL, /* traverseproc tp_traverse; */
1662 /* delete references to contained objects */
1663 NULL, /* inquiry tp_clear; */
1665 /* Assigned meaning in release 2.1 */
1666 /* rich comparisons */
1667 NULL, /* richcmpfunc tp_richcompare; */
1669 /* weak reference enabler */
1670 0, /* Py_ssize_t tp_weaklistoffset; */
1672 /* Added in release 2.2 */
1674 NULL, /* getiterfunc tp_iter; */
1675 NULL, /* iternextfunc tp_iternext; */
1677 /* Attribute descriptor and subclassing stuff */
1678 ra_methods, /* struct PyMethodDef *tp_methods; */
1679 ra_members, /* struct PyMemberDef *tp_members; */
1680 ra_getsetters, /* struct PyGetSetDef *tp_getset; */
1681 NULL, /* struct _typeobject *tp_base; */
1682 NULL, /* PyObject *tp_dict; */
1683 NULL, /* descrgetfunc tp_descr_get; */
1684 NULL, /* descrsetfunc tp_descr_set; */
1685 0, /* Py_ssize_t tp_dictoffset; */
1686 NULL, /* initproc tp_init; */
1687 NULL, /* allocfunc tp_alloc; */
1688 ra_new, /* newfunc tp_new; */
1695 svn_auth_provider_object_t *provider;
1696 } AuthProviderObject;
1698 static void auth_provider_dealloc(PyObject *self)
1700 AuthProviderObject *auth_provider = (AuthProviderObject *)self;
1701 apr_pool_destroy(auth_provider->pool);
1705 PyTypeObject AuthProvider_Type = {
1706 PyObject_HEAD_INIT(NULL) 0,
1707 "ra.AuthProvider", /* const char *tp_name; For printing, in format "<module>.<name>" */
1708 sizeof(AuthProviderObject),
1709 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
1711 /* Methods to implement standard operations */
1713 auth_provider_dealloc, /* destructor tp_dealloc; */
1717 static PyObject *auth_init(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1719 char *kwnames[] = { "providers", NULL };
1720 apr_array_header_t *c_providers;
1721 svn_auth_provider_object_t **el;
1722 PyObject *providers = Py_None;
1726 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwnames, &providers))
1729 ret = PyObject_New(AuthObject, &Auth_Type);
1733 if (!PyList_Check(providers)) {
1734 PyErr_SetString(PyExc_TypeError, "Auth providers should be list");
1738 ret->pool = Pool(NULL);
1739 if (ret->pool == NULL)
1742 ret->providers = providers;
1743 Py_INCREF(providers);
1745 c_providers = apr_array_make(ret->pool, PyList_Size(providers), sizeof(svn_auth_provider_object_t *));
1746 if (c_providers == NULL) {
1750 for (i = 0; i < PyList_Size(providers); i++) {
1751 AuthProviderObject *provider;
1752 el = (svn_auth_provider_object_t **)apr_array_push(c_providers);
1753 /* FIXME: Check that provider is indeed a AuthProviderObject object */
1754 provider = (AuthProviderObject *)PyList_GetItem(providers, i);
1755 *el = provider->provider;
1757 svn_auth_open(&ret->auth_baton, c_providers, ret->pool);
1758 return (PyObject *)ret;
1761 static PyObject *auth_set_parameter(PyObject *self, PyObject *args)
1763 AuthObject *auth = (AuthObject *)self;
1767 if (!PyArg_ParseTuple(args, "sO", &name, &value))
1770 if (!strcmp(name, SVN_AUTH_PARAM_SSL_SERVER_FAILURES)) {
1771 vvalue = apr_pcalloc(auth->pool, sizeof(apr_uint32_t));
1772 *((apr_uint32_t *)vvalue) = PyInt_AsLong(value);
1773 } else if (!strcmp(name, SVN_AUTH_PARAM_DEFAULT_USERNAME) ||
1774 !strcmp(name, SVN_AUTH_PARAM_DEFAULT_PASSWORD)) {
1775 vvalue = apr_pstrdup(auth->pool, PyString_AsString(value));
1777 PyErr_Format(PyExc_TypeError, "Unsupported auth parameter %s", name);
1781 svn_auth_set_parameter(auth->auth_baton, name, (char *)vvalue);
1786 static PyObject *auth_get_parameter(PyObject *self, PyObject *args)
1790 AuthObject *auth = (AuthObject *)self;
1792 if (!PyArg_ParseTuple(args, "s", &name))
1795 value = svn_auth_get_parameter(auth->auth_baton, name);
1797 if (!strcmp(name, SVN_AUTH_PARAM_SSL_SERVER_FAILURES)) {
1798 return PyInt_FromLong(*((apr_uint32_t *)value));
1799 } else if (!strcmp(name, SVN_AUTH_PARAM_DEFAULT_USERNAME) ||
1800 !strcmp(name, SVN_AUTH_PARAM_DEFAULT_PASSWORD)) {
1801 return PyString_FromString((const char *)value);
1803 PyErr_Format(PyExc_TypeError, "Unsupported auth parameter %s", name);
1812 svn_auth_iterstate_t *state;
1814 } CredentialsIterObject;
1816 static PyObject *auth_first_credentials(PyObject *self, PyObject *args)
1820 AuthObject *auth = (AuthObject *)self;
1823 CredentialsIterObject *ret;
1824 svn_auth_iterstate_t *state;
1826 if (!PyArg_ParseTuple(args, "ss", &cred_kind, &realmstring))
1833 RUN_SVN_WITH_POOL(pool,
1834 svn_auth_first_credentials(&creds, &state, cred_kind, realmstring, auth->auth_baton, pool));
1836 ret = PyObject_New(CredentialsIterObject, &CredentialsIter_Type);
1841 ret->cred_kind = apr_pstrdup(pool, cred_kind);
1843 ret->credentials = creds;
1845 return (PyObject *)ret;
1848 static void credentials_iter_dealloc(PyObject *self)
1850 CredentialsIterObject *credsiter = (CredentialsIterObject *)self;
1851 apr_pool_destroy(credsiter->pool);
1855 static PyObject *credentials_iter_next(CredentialsIterObject *iterator)
1859 if (iterator->credentials == NULL) {
1860 PyErr_SetString(PyExc_StopIteration, "No more credentials available");
1864 if (!strcmp(iterator->cred_kind, SVN_AUTH_CRED_SIMPLE)) {
1865 svn_auth_cred_simple_t *simple = iterator->credentials;
1866 ret = Py_BuildValue("(zzb)", simple->username, simple->password, simple->may_save);
1867 } else if (!strcmp(iterator->cred_kind, SVN_AUTH_CRED_USERNAME)) {
1868 svn_auth_cred_username_t *uname = iterator->credentials;
1869 ret = Py_BuildValue("(zb)", uname->username, uname->may_save);
1870 } else if (!strcmp(iterator->cred_kind, SVN_AUTH_CRED_SSL_CLIENT_CERT)) {
1871 svn_auth_cred_ssl_client_cert_t *ccert = iterator->credentials;
1872 ret = Py_BuildValue("(zb)", ccert->cert_file, ccert->may_save);
1873 } else if (!strcmp(iterator->cred_kind, SVN_AUTH_CRED_SSL_CLIENT_CERT_PW)) {
1874 svn_auth_cred_ssl_client_cert_pw_t *ccert = iterator->credentials;
1875 ret = Py_BuildValue("(zb)", ccert->password, ccert->may_save);
1876 } else if (!strcmp(iterator->cred_kind, SVN_AUTH_CRED_SSL_SERVER_TRUST)) {
1877 svn_auth_cred_ssl_server_trust_t *ccert = iterator->credentials;
1878 ret = Py_BuildValue("(ib)", ccert->accepted_failures, ccert->may_save);
1880 PyErr_Format(PyExc_RuntimeError, "Unknown cred kind %s", iterator->cred_kind);
1884 RUN_SVN_WITH_POOL(iterator->pool,
1885 svn_auth_next_credentials(&iterator->credentials, iterator->state, iterator->pool));
1890 PyTypeObject CredentialsIter_Type = {
1891 PyObject_HEAD_INIT(NULL) 0,
1892 "ra.CredentialsIter", /* const char *tp_name; For printing, in format "<module>.<name>" */
1893 sizeof(CredentialsIterObject),
1894 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
1896 /* Methods to implement standard operations */
1898 (destructor)credentials_iter_dealloc, /* destructor tp_dealloc; */
1899 NULL, /* printfunc tp_print; */
1900 NULL, /* getattrfunc tp_getattr; */
1901 NULL, /* setattrfunc tp_setattr; */
1902 NULL, /* cmpfunc tp_compare; */
1903 NULL, /* reprfunc tp_repr; */
1905 /* Method suites for standard classes */
1907 NULL, /* PyNumberMethods *tp_as_number; */
1908 NULL, /* PySequenceMethods *tp_as_sequence; */
1909 NULL, /* PyMappingMethods *tp_as_mapping; */
1911 /* More standard operations (here for binary compatibility) */
1913 NULL, /* hashfunc tp_hash; */
1914 NULL, /* ternaryfunc tp_call; */
1915 NULL, /* reprfunc tp_str; */
1916 NULL, /* getattrofunc tp_getattro; */
1917 NULL, /* setattrofunc tp_setattro; */
1919 /* Functions to access object as input/output buffer */
1920 NULL, /* PyBufferProcs *tp_as_buffer; */
1922 /* Flags to define presence of optional/expanded features */
1923 0, /* long tp_flags; */
1925 NULL, /* const char *tp_doc; Documentation string */
1927 /* Assigned meaning in release 2.0 */
1928 /* call function for all accessible objects */
1929 NULL, /* traverseproc tp_traverse; */
1931 /* delete references to contained objects */
1932 NULL, /* inquiry tp_clear; */
1934 /* Assigned meaning in release 2.1 */
1935 /* rich comparisons */
1936 NULL, /* richcmpfunc tp_richcompare; */
1938 /* weak reference enabler */
1939 0, /* Py_ssize_t tp_weaklistoffset; */
1941 /* Added in release 2.2 */
1943 NULL, /* getiterfunc tp_iter; */
1944 (iternextfunc)credentials_iter_next, /* iternextfunc tp_iternext; */
1948 static PyMethodDef auth_methods[] = {
1949 { "set_parameter", auth_set_parameter, METH_VARARGS, NULL },
1950 { "get_parameter", auth_get_parameter, METH_VARARGS, NULL },
1951 { "credentials", auth_first_credentials, METH_VARARGS, NULL },
1955 static void auth_dealloc(PyObject *self)
1957 AuthObject *auth = (AuthObject *)self;
1958 apr_pool_destroy(auth->pool);
1959 Py_DECREF(auth->providers);
1962 PyTypeObject Auth_Type = {
1963 PyObject_HEAD_INIT(NULL) 0,
1964 "ra.Auth", /* const char *tp_name; For printing, in format "<module>.<name>" */
1966 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
1968 /* Methods to implement standard operations */
1970 auth_dealloc, /* destructor tp_dealloc; */
1971 NULL, /* printfunc tp_print; */
1972 NULL, /* getattrfunc tp_getattr; */
1973 NULL, /* setattrfunc tp_setattr; */
1974 NULL, /* cmpfunc tp_compare; */
1975 NULL, /* reprfunc tp_repr; */
1977 /* Method suites for standard classes */
1979 NULL, /* PyNumberMethods *tp_as_number; */
1980 NULL, /* PySequenceMethods *tp_as_sequence; */
1981 NULL, /* PyMappingMethods *tp_as_mapping; */
1983 /* More standard operations (here for binary compatibility) */
1985 NULL, /* hashfunc tp_hash; */
1986 NULL, /* ternaryfunc tp_call; */
1987 NULL, /* reprfunc tp_str; */
1988 NULL, /* getattrofunc tp_getattro; */
1989 NULL, /* setattrofunc tp_setattro; */
1991 /* Functions to access object as input/output buffer */
1992 NULL, /* PyBufferProcs *tp_as_buffer; */
1994 /* Flags to define presence of optional/expanded features */
1995 0, /* long tp_flags; */
1997 NULL, /* const char *tp_doc; Documentation string */
1999 /* Assigned meaning in release 2.0 */
2000 /* call function for all accessible objects */
2001 NULL, /* traverseproc tp_traverse; */
2003 /* delete references to contained objects */
2004 NULL, /* inquiry tp_clear; */
2006 /* Assigned meaning in release 2.1 */
2007 /* rich comparisons */
2008 NULL, /* richcmpfunc tp_richcompare; */
2010 /* weak reference enabler */
2011 0, /* Py_ssize_t tp_weaklistoffset; */
2013 /* Added in release 2.2 */
2015 NULL, /* getiterfunc tp_iter; */
2016 NULL, /* iternextfunc tp_iternext; */
2018 /* Attribute descriptor and subclassing stuff */
2019 auth_methods, /* struct PyMethodDef *tp_methods; */
2020 NULL, /* struct PyMemberDef *tp_members; */
2021 NULL, /* struct PyGetSetDef *tp_getset; */
2022 NULL, /* struct _typeobject *tp_base; */
2023 NULL, /* PyObject *tp_dict; */
2024 NULL, /* descrgetfunc tp_descr_get; */
2025 NULL, /* descrsetfunc tp_descr_set; */
2026 0, /* Py_ssize_t tp_dictoffset; */
2027 NULL, /* initproc tp_init; */
2028 NULL, /* allocfunc tp_alloc; */
2029 auth_init, /* newfunc tp_new; */
2033 static svn_error_t *py_username_prompt(svn_auth_cred_username_t **cred, void *baton, const char *realm, int may_save, apr_pool_t *pool)
2035 PyObject *fn = (PyObject *)baton, *ret;
2036 PyObject *py_username, *py_may_save;
2037 ret = PyObject_CallFunction(fn, "sb", realm, may_save);
2039 return py_svn_error();
2044 if (!PyTuple_Check(ret)) {
2045 PyErr_SetString(PyExc_TypeError, "expected tuple with username credentials");
2046 return py_svn_error();
2049 if (PyTuple_Size(ret) != 2) {
2050 PyErr_SetString(PyExc_TypeError, "expected tuple with username credentials to be size 2");
2051 return py_svn_error();
2054 py_may_save = PyTuple_GetItem(ret, 1);
2055 if (!PyBool_Check(py_may_save)) {
2056 PyErr_SetString(PyExc_TypeError, "may_save should be boolean");
2057 return py_svn_error();
2059 py_username = PyTuple_GetItem(ret, 0);
2060 if (!PyString_Check(py_username)) {
2061 PyErr_SetString(PyExc_TypeError, "username hsould be string");
2062 return py_svn_error();
2065 *cred = apr_pcalloc(pool, sizeof(**cred));
2066 (*cred)->username = apr_pstrdup(pool, PyString_AsString(py_username));
2067 (*cred)->may_save = (py_may_save == Py_True);
2072 static PyObject *get_username_prompt_provider(PyObject *self, PyObject *args)
2074 AuthProviderObject *auth;
2075 PyObject *prompt_func;
2077 if (!PyArg_ParseTuple(args, "Oi", &prompt_func, &retry_limit))
2079 auth = PyObject_New(AuthProviderObject, &AuthProvider_Type);
2080 auth->pool = Pool(NULL);
2081 if (auth->pool == NULL)
2083 Py_INCREF(prompt_func);
2084 svn_auth_get_username_prompt_provider(&auth->provider, py_username_prompt, (void *)prompt_func, retry_limit, auth->pool);
2085 return (PyObject *)auth;
2088 static svn_error_t *py_simple_prompt(svn_auth_cred_simple_t **cred, void *baton, const char *realm, const char *username, int may_save, apr_pool_t *pool)
2090 PyObject *fn = (PyObject *)baton, *ret;
2091 PyObject *py_may_save, *py_username, *py_password;
2092 ret = PyObject_CallFunction(fn, "ssb", realm, username, may_save);
2094 return py_svn_error();
2095 if (!PyTuple_Check(ret)) {
2096 PyErr_SetString(PyExc_TypeError, "expected tuple with simple credentials");
2097 return py_svn_error();
2099 if (PyTuple_Size(ret) != 3) {
2100 PyErr_SetString(PyExc_TypeError, "expected tuple of size 3");
2101 return py_svn_error();
2104 py_may_save = PyTuple_GetItem(ret, 2);
2106 if (!PyBool_Check(py_may_save)) {
2107 PyErr_SetString(PyExc_TypeError, "may_save should be boolean");
2108 return py_svn_error();
2111 py_username = PyTuple_GetItem(ret, 0);
2112 if (!PyString_Check(py_username)) {
2113 PyErr_SetString(PyExc_TypeError, "username should be string");
2114 return py_svn_error();
2117 py_password = PyTuple_GetItem(ret, 1);
2118 if (!PyString_Check(py_password)) {
2119 PyErr_SetString(PyExc_TypeError, "password should be string");
2120 return py_svn_error();
2123 *cred = apr_pcalloc(pool, sizeof(**cred));
2124 (*cred)->username = apr_pstrdup(pool, PyString_AsString(py_username));
2125 (*cred)->password = apr_pstrdup(pool, PyString_AsString(py_password));
2126 (*cred)->may_save = (py_may_save == Py_True);
2131 static PyObject *get_simple_prompt_provider(PyObject *self, PyObject *args)
2133 PyObject *prompt_func;
2135 AuthProviderObject *auth;
2137 if (!PyArg_ParseTuple(args, "Oi", &prompt_func, &retry_limit))
2140 auth = PyObject_New(AuthProviderObject, &AuthProvider_Type);
2141 auth->pool = Pool(NULL);
2142 if (auth->pool == NULL)
2144 Py_INCREF(prompt_func);
2145 svn_auth_get_simple_prompt_provider (&auth->provider, py_simple_prompt, (void *)prompt_func, retry_limit, auth->pool);
2146 return (PyObject *)auth;
2149 static svn_error_t *py_ssl_server_trust_prompt(svn_auth_cred_ssl_server_trust_t **cred, void *baton, const char *realm, apr_uint32_t failures, const svn_auth_ssl_server_cert_info_t *cert_info, svn_boolean_t may_save, apr_pool_t *pool)
2151 PyObject *fn = (PyObject *)baton;
2153 PyObject *py_cert, *py_may_save, *py_accepted_failures;
2155 if (cert_info == NULL) {
2158 py_cert = Py_BuildValue("(sssss)", cert_info->hostname, cert_info->fingerprint,
2159 cert_info->valid_from, cert_info->valid_until,
2160 cert_info->issuer_dname, cert_info->ascii_cert);
2163 ret = PyObject_CallFunction(fn, "slOb", realm, failures, py_cert, may_save);
2166 return py_svn_error();
2168 if (!PyTuple_Check(ret)) {
2169 PyErr_SetString(PyExc_TypeError, "expected tuple with server trust credentials");
2170 return py_svn_error();
2172 if (PyTuple_Size(ret) != 2) {
2173 PyErr_SetString(PyExc_TypeError, "expected tuple of size 2");
2174 return py_svn_error();
2177 py_accepted_failures = PyTuple_GetItem(ret, 0);
2178 if (!PyInt_Check(py_accepted_failures)) {
2179 PyErr_SetString(PyExc_TypeError, "accepted_failures should be integer");
2180 return py_svn_error();
2183 py_may_save = PyTuple_GetItem(ret, 1);
2184 if (!PyBool_Check(py_may_save)) {
2185 PyErr_SetString(PyExc_TypeError, "may_save should be boolean");
2186 return py_svn_error();
2189 *cred = apr_pcalloc(pool, sizeof(**cred));
2190 (*cred)->accepted_failures = PyInt_AsLong(py_accepted_failures);
2191 (*cred)->may_save = (py_may_save == Py_True);
2197 static PyObject *get_ssl_server_trust_prompt_provider(PyObject *self, PyObject *args)
2199 AuthProviderObject *auth;
2200 PyObject *prompt_func;
2202 if (!PyArg_ParseTuple(args, "O", &prompt_func))
2205 auth = PyObject_New(AuthProviderObject, &AuthProvider_Type);
2208 auth->pool = Pool(NULL);
2209 if (auth->pool == NULL)
2211 Py_INCREF(prompt_func);
2212 svn_auth_get_ssl_server_trust_prompt_provider (&auth->provider, py_ssl_server_trust_prompt, (void *)prompt_func, auth->pool);
2213 return (PyObject *)auth;
2216 static svn_error_t *py_ssl_client_cert_pw_prompt(svn_auth_cred_ssl_client_cert_pw_t **cred, void *baton, const char *realm, svn_boolean_t may_save, apr_pool_t *pool)
2218 PyObject *fn = (PyObject *)baton, *ret, *py_may_save, *py_password;
2219 ret = PyObject_CallFunction(fn, "sb", realm, may_save);
2221 return py_svn_error();
2222 if (!PyTuple_Check(ret)) {
2223 PyErr_SetString(PyExc_TypeError, "expected tuple with client cert pw credentials");
2224 return py_svn_error();
2227 if (PyTuple_Size(ret) != 2) {
2228 PyErr_SetString(PyExc_TypeError, "expected tuple of size 2");
2229 return py_svn_error();
2231 py_may_save = PyTuple_GetItem(ret, 1);
2232 if (!PyBool_Check(py_may_save)) {
2233 PyErr_SetString(PyExc_TypeError, "may_save should be boolean");
2234 return py_svn_error();
2236 py_password = PyTuple_GetItem(ret, 0);
2237 if (!PyString_Check(py_password)) {
2238 PyErr_SetString(PyExc_TypeError, "password should be string");
2239 return py_svn_error();
2241 *cred = apr_pcalloc(pool, sizeof(**cred));
2242 (*cred)->password = apr_pstrdup(pool, PyString_AsString(py_password));
2243 (*cred)->may_save = (py_may_save == Py_True);
2248 static svn_error_t *py_ssl_client_cert_prompt(svn_auth_cred_ssl_client_cert_t **cred, void *baton, const char *realm, svn_boolean_t may_save, apr_pool_t *pool)
2250 PyObject *fn = (PyObject *)baton, *ret, *py_may_save, *py_cert_file;
2251 ret = PyObject_CallFunction(fn, "sb", realm, may_save);
2253 return py_svn_error();
2255 if (!PyTuple_Check(ret)) {
2256 PyErr_SetString(PyExc_TypeError, "expected tuple with client cert credentials");
2257 return py_svn_error();
2260 if (PyTuple_Size(ret) != 2) {
2261 PyErr_SetString(PyExc_TypeError, "expected tuple of size 2");
2262 return py_svn_error();
2264 py_may_save = PyTuple_GetItem(ret, 1);
2265 if (!PyBool_Check(py_may_save)) {
2266 PyErr_SetString(PyExc_TypeError, "may_save should be boolean");
2267 return py_svn_error();
2270 py_cert_file = PyTuple_GetItem(ret, 0);
2271 if (!PyString_Check(py_cert_file)) {
2272 PyErr_SetString(PyExc_TypeError, "cert_file should be string");
2273 return py_svn_error();
2276 *cred = apr_pcalloc(pool, sizeof(**cred));
2277 (*cred)->cert_file = apr_pstrdup(pool, PyString_AsString(py_cert_file));
2278 (*cred)->may_save = (py_may_save == Py_True);
2285 static PyObject *get_ssl_client_cert_pw_prompt_provider(PyObject *self, PyObject *args)
2287 PyObject *prompt_func;
2289 AuthProviderObject *auth;
2291 if (!PyArg_ParseTuple(args, "Oi", &prompt_func, &retry_limit))
2294 auth = PyObject_New(AuthProviderObject, &AuthProvider_Type);
2297 auth->pool = Pool(NULL);
2298 if (auth->pool == NULL)
2300 Py_INCREF(prompt_func);
2301 svn_auth_get_ssl_client_cert_pw_prompt_provider (&auth->provider, py_ssl_client_cert_pw_prompt, (void *)prompt_func, retry_limit, auth->pool);
2302 return (PyObject *)auth;
2305 static PyObject *get_ssl_client_cert_prompt_provider(PyObject *self, PyObject *args)
2307 PyObject *prompt_func;
2309 AuthProviderObject *auth;
2311 if (!PyArg_ParseTuple(args, "Oi", &prompt_func, &retry_limit))
2314 auth = PyObject_New(AuthProviderObject, &AuthProvider_Type);
2317 auth->pool = Pool(NULL);
2318 if (auth->pool == NULL)
2320 Py_INCREF(prompt_func);
2321 svn_auth_get_ssl_client_cert_prompt_provider (&auth->provider, py_ssl_client_cert_prompt, (void *)prompt_func, retry_limit, auth->pool);
2322 return (PyObject *)auth;
2325 static PyObject *get_username_provider(PyObject *self)
2327 AuthProviderObject *auth;
2328 auth = PyObject_New(AuthProviderObject, &AuthProvider_Type);
2331 auth->pool = Pool(NULL);
2332 if (auth->pool == NULL)
2334 svn_auth_get_username_provider(&auth->provider, auth->pool);
2335 return (PyObject *)auth;
2338 static PyObject *get_simple_provider(PyObject *self)
2340 AuthProviderObject *auth = PyObject_New(AuthProviderObject,
2341 &AuthProvider_Type);
2342 auth->pool = Pool(NULL);
2343 if (auth->pool == NULL)
2345 svn_auth_get_simple_provider(&auth->provider, auth->pool);
2346 return (PyObject *)auth;
2349 static PyObject *get_ssl_server_trust_file_provider(PyObject *self)
2351 AuthProviderObject *auth = PyObject_New(AuthProviderObject, &AuthProvider_Type);
2352 auth->pool = Pool(NULL);
2353 if (auth->pool == NULL)
2355 svn_auth_get_ssl_server_trust_file_provider(&auth->provider, auth->pool);
2356 return (PyObject *)auth;
2359 static PyObject *get_ssl_client_cert_file_provider(PyObject *self)
2361 AuthProviderObject *auth = PyObject_New(AuthProviderObject, &AuthProvider_Type);
2362 auth->pool = Pool(NULL);
2363 if (auth->pool == NULL)
2365 svn_auth_get_ssl_client_cert_file_provider(&auth->provider, auth->pool);
2366 return (PyObject *)auth;
2369 static PyObject *get_ssl_client_cert_pw_file_provider(PyObject *self)
2371 AuthProviderObject *auth = PyObject_New(AuthProviderObject, &AuthProvider_Type);
2372 auth->pool = Pool(NULL);
2373 if (auth->pool == NULL)
2375 svn_auth_get_ssl_client_cert_pw_file_provider(&auth->provider, auth->pool);
2376 return (PyObject *)auth;
2379 static PyMethodDef ra_module_methods[] = {
2380 { "version", (PyCFunction)version, METH_NOARGS, NULL },
2381 { "get_ssl_client_cert_pw_file_provider", (PyCFunction)get_ssl_client_cert_pw_file_provider, METH_NOARGS, NULL },
2382 { "get_ssl_client_cert_file_provider", (PyCFunction)get_ssl_client_cert_file_provider, METH_NOARGS, NULL },
2383 { "get_ssl_server_trust_file_provider", (PyCFunction)get_ssl_server_trust_file_provider, METH_NOARGS, NULL },
2384 { "get_simple_provider", (PyCFunction)get_simple_provider, METH_NOARGS, NULL },
2385 { "get_username_prompt_provider", (PyCFunction)get_username_prompt_provider, METH_VARARGS, NULL },
2386 { "get_simple_prompt_provider", (PyCFunction)get_simple_prompt_provider, METH_VARARGS, NULL },
2387 { "get_ssl_server_trust_prompt_provider", (PyCFunction)get_ssl_server_trust_prompt_provider, METH_VARARGS, NULL },
2388 { "get_ssl_client_cert_prompt_provider", (PyCFunction)get_ssl_client_cert_prompt_provider, METH_VARARGS, NULL },
2389 { "get_ssl_client_cert_pw_prompt_provider", (PyCFunction)get_ssl_client_cert_pw_prompt_provider, METH_VARARGS, NULL },
2390 { "get_username_provider", (PyCFunction)get_username_provider, METH_NOARGS, NULL },
2396 static apr_pool_t *pool;
2399 if (PyType_Ready(&RemoteAccess_Type) < 0)
2402 if (PyType_Ready(&Editor_Type) < 0)
2405 if (PyType_Ready(&FileEditor_Type) < 0)
2408 if (PyType_Ready(&DirectoryEditor_Type) < 0)
2411 if (PyType_Ready(&Reporter_Type) < 0)
2414 if (PyType_Ready(&TxDeltaWindowHandler_Type) < 0)
2417 if (PyType_Ready(&Auth_Type) < 0)
2420 if (PyType_Ready(&CredentialsIter_Type) < 0)
2423 if (PyType_Ready(&AuthProvider_Type) < 0)
2430 svn_ra_initialize(pool);
2432 mod = Py_InitModule3("ra", ra_module_methods, "Remote Access");
2436 PyModule_AddObject(mod, "RemoteAccess", (PyObject *)&RemoteAccess_Type);
2437 Py_INCREF(&RemoteAccess_Type);
2439 PyModule_AddObject(mod, "Auth", (PyObject *)&Auth_Type);
2440 Py_INCREF(&Auth_Type);
2442 busy_exc = PyErr_NewException("ra.BusyException", NULL, NULL);
2443 PyModule_AddObject(mod, "BusyException", busy_exc);
2445 PyModule_AddIntConstant(mod, "DIRENT_KIND", SVN_DIRENT_KIND);
2446 PyModule_AddIntConstant(mod, "DIRENT_SIZE", SVN_DIRENT_SIZE);
2447 PyModule_AddIntConstant(mod, "DIRENT_HAS_PROPS", SVN_DIRENT_HAS_PROPS);
2448 PyModule_AddIntConstant(mod, "DIRENT_CREATED_REV", SVN_DIRENT_CREATED_REV);
2449 PyModule_AddIntConstant(mod, "DIRENT_TIME", SVN_DIRENT_TIME);
2450 PyModule_AddIntConstant(mod, "DIRENT_LAST_AUTHOR", SVN_DIRENT_LAST_AUTHOR);
2451 PyModule_AddIntConstant(mod, "DIRENT_ALL", SVN_DIRENT_ALL);
2453 #ifdef SVN_VER_REVISION
2454 PyModule_AddIntConstant(mod, "SVN_REVISION", SVN_VER_REVISION);