2 * Copyright © 2008 Jelmer Vernooij <jelmer@samba.org>
3 * -*- coding: utf-8 -*-
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation; either version 2.1 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <apr_general.h>
24 #include <svn_repos.h>
29 extern PyTypeObject FileSystemRoot_Type;
30 extern PyTypeObject Repository_Type;
31 extern PyTypeObject FileSystem_Type;
32 extern PyTypeObject Stream_Type;
40 static PyObject *repos_create(PyObject *self, PyObject *args)
43 PyObject *config=Py_None, *fs_config=Py_None;
44 svn_repos_t *repos = NULL;
46 apr_hash_t *hash_config, *hash_fs_config;
47 RepositoryObject *ret;
49 if (!PyArg_ParseTuple(args, "s|OO:create", &path, &config, &fs_config))
55 hash_config = config_hash_from_object(config, pool);
56 if (hash_config == NULL)
58 hash_fs_config = apr_hash_make(pool); /* FIXME */
59 if (hash_fs_config == NULL) {
60 PyErr_SetString(PyExc_RuntimeError, "Unable to create fs config hash");
63 RUN_SVN_WITH_POOL(pool, svn_repos_create(&repos,
64 svn_path_canonicalize(path, pool), NULL, NULL,
65 hash_config, hash_fs_config, pool));
67 ret = PyObject_New(RepositoryObject, &Repository_Type);
74 return (PyObject *)ret;
77 static void repos_dealloc(PyObject *self)
79 RepositoryObject *repos = (RepositoryObject *)self;
81 apr_pool_destroy(repos->pool);
85 static PyObject *repos_init(PyTypeObject *type, PyObject *args, PyObject *kwargs)
88 char *kwnames[] = { "path", NULL };
90 RepositoryObject *ret;
92 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwnames, &path))
95 ret = PyObject_New(RepositoryObject, &Repository_Type);
99 ret->pool = Pool(NULL);
100 if (ret->pool == NULL)
102 Py_BEGIN_ALLOW_THREADS
103 err = svn_repos_open(&ret->repos, svn_path_canonicalize(path, ret->pool),
108 handle_svn_error(err);
109 svn_error_clear(err);
114 return (PyObject *)ret;
121 } FileSystemRootObject;
125 RepositoryObject *repos;
130 static PyObject *repos_fs(PyObject *self)
132 RepositoryObject *reposobj = (RepositoryObject *)self;
133 FileSystemObject *ret;
136 fs = svn_repos_fs(reposobj->repos);
139 PyErr_SetString(PyExc_RuntimeError, "Unable to obtain fs handle");
143 ret = PyObject_New(FileSystemObject, &FileSystem_Type);
148 ret->repos = reposobj;
149 ret->pool = reposobj->pool;
152 return (PyObject *)ret;
155 static PyObject *fs_get_uuid(PyObject *self)
157 FileSystemObject *fsobj = (FileSystemObject *)self;
160 apr_pool_t *temp_pool;
162 temp_pool = Pool(NULL);
163 if (temp_pool == NULL)
165 RUN_SVN_WITH_POOL(temp_pool, svn_fs_get_uuid(fsobj->fs, &uuid, temp_pool));
166 ret = PyString_FromString(uuid);
167 apr_pool_destroy(temp_pool);
172 static PyObject *fs_get_youngest_revision(FileSystemObject *self)
175 apr_pool_t *temp_pool;
178 temp_pool = Pool(NULL);
179 if (temp_pool == NULL)
181 RUN_SVN_WITH_POOL(temp_pool, svn_fs_youngest_rev(&rev, self->fs, temp_pool));
182 ret = PyInt_FromLong(rev);
183 apr_pool_destroy(temp_pool);
188 static PyObject *fs_get_revision_root(FileSystemObject *self, PyObject *args)
191 FileSystemRootObject *ret;
195 if (!PyArg_ParseTuple(args, "l", &rev))
202 RUN_SVN_WITH_POOL(pool, svn_fs_revision_root(&root, self->fs, rev, pool));
204 ret = PyObject_New(FileSystemRootObject, &FileSystemRoot_Type);
211 return (PyObject *)ret;
214 static PyObject *fs_get_revision_proplist(FileSystemObject *self, PyObject *args)
218 apr_pool_t *temp_pool;
221 if (!PyArg_ParseTuple(args, "l", &rev))
224 temp_pool = Pool(NULL);
225 if (temp_pool == NULL)
228 RUN_SVN_WITH_POOL(temp_pool, svn_fs_revision_proplist(&props, self->fs, rev, temp_pool));
230 ret = prop_hash_to_dict(props);
232 apr_pool_destroy(temp_pool);
234 return (PyObject *)ret;
237 static PyMethodDef fs_methods[] = {
238 { "get_uuid", (PyCFunction)fs_get_uuid, METH_NOARGS, NULL },
239 { "youngest_revision", (PyCFunction)fs_get_youngest_revision, METH_NOARGS, NULL },
240 { "revision_root", (PyCFunction)fs_get_revision_root, METH_VARARGS, NULL },
241 { "revision_proplist", (PyCFunction)fs_get_revision_proplist, METH_VARARGS, NULL },
245 static void fs_dealloc(PyObject *self)
247 FileSystemObject *fsobj = (FileSystemObject *)self;
248 Py_DECREF(fsobj->repos);
249 apr_pool_destroy(fsobj->pool);
253 PyTypeObject FileSystem_Type = {
254 PyObject_HEAD_INIT(NULL) 0,
255 "repos.FileSystem", /* const char *tp_name; For printing, in format "<module>.<name>" */
256 sizeof(FileSystemObject),
257 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
259 /* Methods to implement standard operations */
261 fs_dealloc, /* destructor tp_dealloc; */
262 NULL, /* printfunc tp_print; */
263 NULL, /* getattrfunc tp_getattr; */
264 NULL, /* setattrfunc tp_setattr; */
265 NULL, /* cmpfunc tp_compare; */
266 NULL, /* reprfunc tp_repr; */
268 /* Method suites for standard classes */
270 NULL, /* PyNumberMethods *tp_as_number; */
271 NULL, /* PySequenceMethods *tp_as_sequence; */
272 NULL, /* PyMappingMethods *tp_as_mapping; */
274 /* More standard operations (here for binary compatibility) */
276 NULL, /* hashfunc tp_hash; */
277 NULL, /* ternaryfunc tp_call; */
278 NULL, /* reprfunc tp_str; */
279 NULL, /* getattrofunc tp_getattro; */
280 NULL, /* setattrofunc tp_setattro; */
282 /* Functions to access object as input/output buffer */
283 NULL, /* PyBufferProcs *tp_as_buffer; */
285 /* Flags to define presence of optional/expanded features */
286 0, /* long tp_flags; */
288 NULL, /* const char *tp_doc; Documentation string */
290 /* Assigned meaning in release 2.0 */
291 /* call function for all accessible objects */
292 NULL, /* traverseproc tp_traverse; */
294 /* delete references to contained objects */
295 NULL, /* inquiry tp_clear; */
297 /* Assigned meaning in release 2.1 */
298 /* rich comparisons */
299 NULL, /* richcmpfunc tp_richcompare; */
301 /* weak reference enabler */
302 0, /* Py_ssize_t tp_weaklistoffset; */
304 /* Added in release 2.2 */
306 NULL, /* getiterfunc tp_iter; */
307 NULL, /* iternextfunc tp_iternext; */
309 /* Attribute descriptor and subclassing stuff */
310 fs_methods, /* struct PyMethodDef *tp_methods; */
314 static PyObject *repos_load_fs(PyObject *self, PyObject *args, PyObject *kwargs)
316 const char *parent_dir = NULL;
317 PyObject *dumpstream, *feedback_stream;
318 unsigned char use_pre_commit_hook = 0, use_post_commit_hook = 0;
319 char *kwnames[] = { "dumpstream", "feedback_stream", "uuid_action",
320 "parent_dir", "use_pre_commit_hook",
321 "use_post_commit_hook", NULL };
323 apr_pool_t *temp_pool;
324 RepositoryObject *reposobj = (RepositoryObject *)self;
326 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|zbb", kwnames,
327 &dumpstream, &feedback_stream, &uuid_action,
328 &parent_dir, &use_pre_commit_hook,
329 &use_post_commit_hook))
332 if (uuid_action != svn_repos_load_uuid_default &&
333 uuid_action != svn_repos_load_uuid_ignore &&
334 uuid_action != svn_repos_load_uuid_force) {
335 PyErr_SetString(PyExc_RuntimeError, "Invalid UUID action");
339 temp_pool = Pool(NULL);
340 if (temp_pool == NULL)
342 RUN_SVN_WITH_POOL(temp_pool, svn_repos_load_fs2(reposobj->repos,
343 new_py_stream(temp_pool, dumpstream),
344 new_py_stream(temp_pool, feedback_stream),
345 uuid_action, parent_dir, use_pre_commit_hook,
346 use_post_commit_hook, py_cancel_check, NULL,
348 apr_pool_destroy(temp_pool);
352 static PyObject *repos_delete(PyObject *self, PyObject *args)
355 apr_pool_t *temp_pool;
357 if (!PyArg_ParseTuple(args, "s", &path))
360 temp_pool = Pool(NULL);
361 if (temp_pool == NULL)
363 RUN_SVN_WITH_POOL(temp_pool, svn_repos_delete(path, temp_pool));
365 apr_pool_destroy(temp_pool);
370 static PyObject *repos_hotcopy(RepositoryObject *self, PyObject *args)
372 char *src_path, *dest_path;
373 svn_boolean_t clean_logs = FALSE;
374 apr_pool_t *temp_pool;
376 if (!PyArg_ParseTuple(args, "ss|b", &src_path, &dest_path, &clean_logs))
379 temp_pool = Pool(NULL);
380 if (temp_pool == NULL)
383 RUN_SVN_WITH_POOL(temp_pool,
384 svn_repos_hotcopy(src_path, dest_path, clean_logs, temp_pool));
386 apr_pool_destroy(temp_pool);
392 * Get runtime libsvn_wc version information.
394 * :return: tuple with major, minor, patch version number and tag.
396 static PyObject *version(PyObject *self)
398 const svn_version_t *ver = svn_repos_version();
399 return Py_BuildValue("(iiis)", ver->major, ver->minor,
400 ver->patch, ver->tag);
403 SVN_VERSION_DEFINE(svn_api_version);
406 * Get compile-time libsvn_wc version information.
408 * :return: tuple with major, minor, patch version number and tag.
410 static PyObject *api_version(PyObject *self)
412 const svn_version_t *ver = &svn_api_version;
413 return Py_BuildValue("(iiis)", ver->major, ver->minor,
414 ver->patch, ver->tag);
417 static PyMethodDef repos_module_methods[] = {
418 { "create", (PyCFunction)repos_create, METH_VARARGS,
419 "create(path, config=None, fs_config=None)\n\n"
420 "Create a new repository." },
421 { "delete", (PyCFunction)repos_delete, METH_VARARGS,
423 "Delete a repository." },
424 { "hotcopy", (PyCFunction)repos_hotcopy, METH_VARARGS,
425 "hotcopy(src_path, dest_path, clean_logs=False)\n\n"
426 "Make a hot copy of a repository." },
427 { "api_version", (PyCFunction)api_version, METH_NOARGS,
428 "api_version() -> (major, minor, patch, tag)\n\n"
429 "Version of libsvn_client Subvertpy was compiled against."
431 { "version", (PyCFunction)version, METH_NOARGS,
432 "version() -> (major, minor, patch, tag)\n\n"
433 "Version of libsvn_wc currently used."
439 static PyObject *repos_has_capability(RepositoryObject *self, PyObject *args)
441 #if ONLY_SINCE_SVN(1, 5)
444 apr_pool_t *temp_pool;
445 if (!PyArg_ParseTuple(args, "s", &name))
447 temp_pool = Pool(NULL);
448 if (temp_pool == NULL)
450 RUN_SVN_WITH_POOL(temp_pool,
451 svn_repos_has_capability(self->repos, &has, name, temp_pool));
452 apr_pool_destroy(temp_pool);
453 return PyBool_FromLong(has);
455 PyErr_SetString(PyExc_NotImplementedError, "has_capability is only supported in Subversion >= 1.5");
460 static PyObject *repos_verify(RepositoryObject *self, PyObject *args)
462 apr_pool_t *temp_pool;
463 PyObject *py_feedback_stream;
464 long start_rev, end_rev;
465 if (!PyArg_ParseTuple(args, "Oii", &py_feedback_stream, &start_rev, &end_rev))
467 temp_pool = Pool(NULL);
468 if (temp_pool == NULL)
470 RUN_SVN_WITH_POOL(temp_pool,
471 svn_repos_verify_fs(self->repos,
472 new_py_stream(temp_pool, py_feedback_stream), start_rev, end_rev,
473 py_cancel_check, NULL, temp_pool));
474 apr_pool_destroy(temp_pool);
479 static svn_error_t *py_pack_notify(void *baton, apr_int64_t shard, svn_fs_pack_notify_action_t action, apr_pool_t *pool)
482 if (baton == Py_None)
484 ret = PyObject_CallFunction((PyObject *)baton, "li", shard, action);
486 return py_svn_error();
491 static PyObject *repos_pack(RepositoryObject *self, PyObject *args)
493 apr_pool_t *temp_pool;
494 PyObject *notify_func = Py_None;
495 if (!PyArg_ParseTuple(args, "|O", ¬ify_func))
497 temp_pool = Pool(NULL);
498 if (temp_pool == NULL)
500 RUN_SVN_WITH_POOL(temp_pool,
501 svn_repos_fs_pack(self->repos, py_pack_notify, notify_func,
502 py_cancel_check, NULL, temp_pool));
503 apr_pool_destroy(temp_pool);
508 static PyMethodDef repos_methods[] = {
509 { "load_fs", (PyCFunction)repos_load_fs, METH_VARARGS|METH_KEYWORDS, NULL },
510 { "fs", (PyCFunction)repos_fs, METH_NOARGS, NULL },
511 { "has_capability", (PyCFunction)repos_has_capability, METH_VARARGS, NULL },
512 { "verify_fs", (PyCFunction)repos_verify, METH_VARARGS,
513 "S.verify_repos(feedback_stream, start_revnum, end_revnum)" },
514 { "pack_fs", (PyCFunction)repos_pack, METH_VARARGS, NULL },
518 PyTypeObject Repository_Type = {
519 PyObject_HEAD_INIT(NULL) 0,
520 "repos.Repository", /* const char *tp_name; For printing, in format "<module>.<name>" */
521 sizeof(RepositoryObject),
522 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
524 /* Methods to implement standard operations */
526 repos_dealloc, /* destructor tp_dealloc; */
527 NULL, /* printfunc tp_print; */
528 NULL, /* getattrfunc tp_getattr; */
529 NULL, /* setattrfunc tp_setattr; */
530 NULL, /* cmpfunc tp_compare; */
531 NULL, /* reprfunc tp_repr; */
533 /* Method suites for standard classes */
535 NULL, /* PyNumberMethods *tp_as_number; */
536 NULL, /* PySequenceMethods *tp_as_sequence; */
537 NULL, /* PyMappingMethods *tp_as_mapping; */
539 /* More standard operations (here for binary compatibility) */
541 NULL, /* hashfunc tp_hash; */
542 NULL, /* ternaryfunc tp_call; */
543 NULL, /* reprfunc tp_str; */
544 NULL, /* getattrofunc tp_getattro; */
545 NULL, /* setattrofunc tp_setattro; */
547 /* Functions to access object as input/output buffer */
548 NULL, /* PyBufferProcs *tp_as_buffer; */
550 /* Flags to define presence of optional/expanded features */
551 0, /* long tp_flags; */
553 "Local repository", /* const char *tp_doc; Documentation string */
555 /* Assigned meaning in release 2.0 */
556 /* call function for all accessible objects */
557 NULL, /* traverseproc tp_traverse; */
559 /* delete references to contained objects */
560 NULL, /* inquiry tp_clear; */
562 /* Assigned meaning in release 2.1 */
563 /* rich comparisons */
564 NULL, /* richcmpfunc tp_richcompare; */
566 /* weak reference enabler */
567 0, /* Py_ssize_t tp_weaklistoffset; */
569 /* Added in release 2.2 */
571 NULL, /* getiterfunc tp_iter; */
572 NULL, /* iternextfunc tp_iternext; */
574 /* Attribute descriptor and subclassing stuff */
575 repos_methods, /* struct PyMethodDef *tp_methods; */
576 NULL, /* struct PyMemberDef *tp_members; */
577 NULL, /* struct PyGetSetDef *tp_getset; */
578 NULL, /* struct _typeobject *tp_base; */
579 NULL, /* PyObject *tp_dict; */
580 NULL, /* descrgetfunc tp_descr_get; */
581 NULL, /* descrsetfunc tp_descr_set; */
582 0, /* Py_ssize_t tp_dictoffset; */
583 NULL, /* initproc tp_init; */
584 NULL, /* allocfunc tp_alloc; */
585 repos_init, /* newfunc tp_new; */
589 static void fs_root_dealloc(PyObject *self)
591 FileSystemRootObject *fsobj = (FileSystemRootObject *)self;
593 apr_pool_destroy(fsobj->pool);
597 static PyObject *py_string_from_svn_node_id(const svn_fs_id_t *id)
599 apr_pool_t *temp_pool;
601 temp_pool = Pool(NULL);
602 if (temp_pool == NULL)
604 str = svn_fs_unparse_id(id, temp_pool);
606 apr_pool_destroy(temp_pool);
609 return PyString_FromStringAndSize(str->data, str->len);
612 #if ONLY_BEFORE_SVN(1, 6)
613 static PyObject *py_fs_path_change(svn_fs_path_change_t *val)
615 PyObject *ret, *py_node_id;
617 py_node_id = py_string_from_svn_node_id(val->node_rev_id);
618 if (py_node_id == NULL) {
621 ret = Py_BuildValue("(Oibb)", py_node_id,
622 val->change_kind, val->text_mod, val->prop_mod);
623 Py_DECREF(py_node_id);
633 static PyObject *py_fs_path_change2(svn_fs_path_change2_t *val)
635 PyObject *ret, *py_node_id;
637 py_node_id = py_string_from_svn_node_id(val->node_rev_id);
638 if (py_node_id == NULL) {
641 ret = Py_BuildValue("(Oibb)", py_node_id,
642 val->change_kind, val->text_mod, val->prop_mod);
643 Py_DECREF(py_node_id);
648 /* FIXME: copyfrom information */
654 static PyObject *fs_root_paths_changed(FileSystemRootObject *self)
656 apr_pool_t *temp_pool;
657 apr_hash_t *changed_paths;
660 apr_hash_index_t *idx;
662 temp_pool = Pool(NULL);
663 if (temp_pool == NULL)
665 #if ONLY_SINCE_SVN(1, 6)
666 RUN_SVN_WITH_POOL(temp_pool,
667 svn_fs_paths_changed2(&changed_paths, self->root, temp_pool));
669 RUN_SVN_WITH_POOL(temp_pool,
670 svn_fs_paths_changed(&changed_paths, self->root, temp_pool));
673 for (idx = apr_hash_first(temp_pool, changed_paths); idx != NULL;
674 idx = apr_hash_next(idx)) {
676 #if ONLY_SINCE_SVN(1, 6)
677 svn_fs_path_change2_t *val;
679 svn_fs_path_change_t *val;
681 apr_hash_this(idx, (const void **)&key, &klen, (void **)&val);
682 #if ONLY_SINCE_SVN(1, 6)
683 py_val = py_fs_path_change2(val);
685 py_val = py_fs_path_change(val);
687 if (py_val == NULL) {
688 apr_pool_destroy(temp_pool);
692 PyDict_SetItemString(ret, key, py_val);
695 apr_pool_destroy(temp_pool);
699 static PyObject *fs_root_is_dir(FileSystemRootObject *self, PyObject *args)
701 svn_boolean_t is_dir;
702 apr_pool_t *temp_pool;
705 if (!PyArg_ParseTuple(args, "s", &path))
708 temp_pool = Pool(NULL);
709 if (temp_pool == NULL)
711 RUN_SVN_WITH_POOL(temp_pool, svn_fs_is_dir(&is_dir, self->root,
713 apr_pool_destroy(temp_pool);
714 return PyBool_FromLong(is_dir);
717 static PyObject *fs_root_is_file(FileSystemRootObject *self, PyObject *args)
719 svn_boolean_t is_file;
720 apr_pool_t *temp_pool;
723 if (!PyArg_ParseTuple(args, "s", &path))
726 temp_pool = Pool(NULL);
727 if (temp_pool == NULL)
729 RUN_SVN_WITH_POOL(temp_pool, svn_fs_is_file(&is_file, self->root,
731 apr_pool_destroy(temp_pool);
732 return PyBool_FromLong(is_file);
735 static PyObject *fs_root_file_length(FileSystemRootObject *self, PyObject *args)
737 svn_filesize_t filesize;
738 apr_pool_t *temp_pool;
741 if (!PyArg_ParseTuple(args, "s", &path))
744 temp_pool = Pool(NULL);
745 if (temp_pool == NULL)
747 RUN_SVN_WITH_POOL(temp_pool, svn_fs_file_length(&filesize, self->root,
749 apr_pool_destroy(temp_pool);
750 return PyInt_FromLong(filesize);
753 static PyObject *fs_node_file_proplist(FileSystemRootObject *self, PyObject *args)
755 apr_pool_t *temp_pool;
758 apr_hash_t *proplist;
760 if (!PyArg_ParseTuple(args, "s", &path))
763 temp_pool = Pool(NULL);
764 if (temp_pool == NULL)
766 RUN_SVN_WITH_POOL(temp_pool, svn_fs_node_proplist(&proplist, self->root,
768 ret = prop_hash_to_dict(proplist);
769 apr_pool_destroy(temp_pool);
773 static PyObject *fs_root_file_checksum(FileSystemRootObject *self, PyObject *args)
775 apr_pool_t *temp_pool;
776 svn_boolean_t force = FALSE;
778 #if ONLY_SINCE_SVN(1, 6)
779 svn_checksum_kind_t kind;
781 svn_checksum_t *checksum;
784 unsigned char checksum[APR_MD5_DIGESTSIZE];
788 if (!PyArg_ParseTuple(args, "s|ib", &path, &kind, &force))
791 temp_pool = Pool(NULL);
792 if (temp_pool == NULL)
794 #if ONLY_SINCE_SVN(1, 6)
795 RUN_SVN_WITH_POOL(temp_pool, svn_fs_file_checksum(&checksum, kind,
797 path, force, temp_pool));
798 cstr = svn_checksum_to_cstring(checksum, temp_pool);
803 ret = PyString_FromString(cstr);
807 PyErr_SetString(PyExc_ValueError, "Only MD5 checksums allowed with subversion < 1.6");
811 RUN_SVN_WITH_POOL(temp_pool, svn_fs_file_md5_checksum(checksum,
814 ret = PyString_FromStringAndSize((char *)checksum, APR_MD5_DIGESTSIZE);
816 apr_pool_destroy(temp_pool);
820 static PyObject *fs_root_file_contents(FileSystemRootObject *self, PyObject *args)
822 svn_stream_t *stream;
827 if (!PyArg_ParseTuple(args, "s", &path))
833 RUN_SVN_WITH_POOL(pool, svn_fs_file_contents(&stream, self->root,
836 ret = PyObject_New(StreamObject, &Stream_Type);
842 ret->stream = stream;
844 return (PyObject *)ret;
847 static PyMethodDef fs_root_methods[] = {
848 { "paths_changed", (PyCFunction)fs_root_paths_changed, METH_NOARGS, NULL },
849 { "is_dir", (PyCFunction)fs_root_is_dir, METH_VARARGS, NULL },
850 { "is_file", (PyCFunction)fs_root_is_file, METH_VARARGS, NULL },
851 { "file_length", (PyCFunction)fs_root_file_length, METH_VARARGS, NULL },
852 { "file_content", (PyCFunction)fs_root_file_contents, METH_VARARGS, NULL },
853 { "file_checksum", (PyCFunction)fs_root_file_checksum, METH_VARARGS, NULL },
854 { "proplist", (PyCFunction)fs_node_file_proplist, METH_VARARGS, NULL },
858 PyTypeObject FileSystemRoot_Type = {
859 PyObject_HEAD_INIT(NULL) 0,
860 "repos.FileSystemRoot", /* const char *tp_name; For printing, in format "<module>.<name>" */
861 sizeof(FileSystemRootObject),
862 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
864 /* Methods to implement standard operations */
866 fs_root_dealloc, /* destructor tp_dealloc; */
867 NULL, /* printfunc tp_print; */
868 NULL, /* getattrfunc tp_getattr; */
869 NULL, /* setattrfunc tp_setattr; */
870 NULL, /* cmpfunc tp_compare; */
871 NULL, /* reprfunc tp_repr; */
873 /* Method suites for standard classes */
875 NULL, /* PyNumberMethods *tp_as_number; */
876 NULL, /* PySequenceMethods *tp_as_sequence; */
877 NULL, /* PyMappingMethods *tp_as_mapping; */
879 /* More standard operations (here for binary compatibility) */
881 NULL, /* hashfunc tp_hash; */
882 NULL, /* ternaryfunc tp_call; */
883 NULL, /* reprfunc tp_str; */
884 NULL, /* getattrofunc tp_getattro; */
885 NULL, /* setattrofunc tp_setattro; */
887 /* Functions to access object as input/output buffer */
888 NULL, /* PyBufferProcs *tp_as_buffer; */
890 /* Flags to define presence of optional/expanded features */
891 0, /* long tp_flags; */
893 NULL, /* const char *tp_doc; Documentation string */
895 /* Assigned meaning in release 2.0 */
896 /* call function for all accessible objects */
897 NULL, /* traverseproc tp_traverse; */
899 /* delete references to contained objects */
900 NULL, /* inquiry tp_clear; */
902 /* Assigned meaning in release 2.1 */
903 /* rich comparisons */
904 NULL, /* richcmpfunc tp_richcompare; */
906 /* weak reference enabler */
907 0, /* Py_ssize_t tp_weaklistoffset; */
909 /* Added in release 2.2 */
911 NULL, /* getiterfunc tp_iter; */
912 NULL, /* iternextfunc tp_iternext; */
914 /* Attribute descriptor and subclassing stuff */
915 fs_root_methods, /* struct PyMethodDef *tp_methods; */
921 static apr_pool_t *pool;
924 if (PyType_Ready(&Repository_Type) < 0)
927 if (PyType_Ready(&FileSystem_Type) < 0)
930 if (PyType_Ready(&FileSystemRoot_Type) < 0)
933 if (PyType_Ready(&Stream_Type) < 0)
941 svn_fs_initialize(pool);
943 mod = Py_InitModule3("repos", repos_module_methods, "Local repository management");
947 PyModule_AddObject(mod, "LOAD_UUID_DEFAULT", PyLong_FromLong(svn_repos_load_uuid_default));
948 PyModule_AddObject(mod, "LOAD_UUID_IGNORE", PyLong_FromLong(svn_repos_load_uuid_ignore));
949 PyModule_AddObject(mod, "LOAD_UUID_FORCE", PyLong_FromLong(svn_repos_load_uuid_force));
951 PyModule_AddObject(mod, "PATH_CHANGE_MODIFY", PyInt_FromLong(svn_fs_path_change_modify));
952 PyModule_AddObject(mod, "PATH_CHANGE_ADD", PyInt_FromLong(svn_fs_path_change_add));
953 PyModule_AddObject(mod, "PATH_CHANGE_DELETE", PyInt_FromLong(svn_fs_path_change_delete));
954 PyModule_AddObject(mod, "PATH_CHANGE_REPLACE", PyInt_FromLong(svn_fs_path_change_replace));
956 #if ONLY_SINCE_SVN(1, 6)
957 PyModule_AddObject(mod, "CHECKSUM_MD5", PyInt_FromLong(svn_checksum_md5));
958 PyModule_AddObject(mod, "CHECKSUM_SHA1", PyInt_FromLong(svn_checksum_sha1));
960 PyModule_AddObject(mod, "CHECKSUM_MD5", PyInt_FromLong(0));
963 PyModule_AddObject(mod, "Repository", (PyObject *)&Repository_Type);
964 Py_INCREF(&Repository_Type);
966 PyModule_AddObject(mod, "Stream", (PyObject *)&Stream_Type);
967 Py_INCREF(&Stream_Type);