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 General Public License as published by
7 * the Free Software Foundation; either version 2 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 General Public License for more details.
15 * You should have received a copy of the GNU 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
20 #include <apr_general.h>
23 #include <structmember.h>
29 extern PyTypeObject Entry_Type;
30 extern PyTypeObject Adm_Type;
32 static PyObject *py_entry(const svn_wc_entry_t *entry);
34 static svn_error_t *py_ra_report_set_path(void *baton, const char *path, svn_revnum_t revision, int start_empty, const char *lock_token, apr_pool_t *pool)
36 PyObject *self = (PyObject *)baton, *py_lock_token, *ret;
37 PyGILState_STATE state = PyGILState_Ensure();
38 if (lock_token == NULL) {
39 py_lock_token = Py_None;
41 py_lock_token = PyString_FromString(lock_token);
43 ret = PyObject_CallMethod(self, "set_path", "slbO", path, revision, start_empty, py_lock_token);
44 CB_CHECK_PYRETVAL(ret);
45 PyGILState_Release(state);
49 static svn_error_t *py_ra_report_delete_path(void *baton, const char *path, apr_pool_t *pool)
51 PyObject *self = (PyObject *)baton, *ret;
52 PyGILState_STATE state = PyGILState_Ensure();
53 ret = PyObject_CallMethod(self, "delete_path", "s", path);
54 CB_CHECK_PYRETVAL(ret);
55 PyGILState_Release(state);
59 static svn_error_t *py_ra_report_link_path(void *report_baton, const char *path, const char *url, svn_revnum_t revision, int start_empty, const char *lock_token, apr_pool_t *pool)
61 PyObject *self = (PyObject *)report_baton, *ret, *py_lock_token;
62 PyGILState_STATE state = PyGILState_Ensure();
63 if (lock_token == NULL) {
64 py_lock_token = Py_None;
66 py_lock_token = PyString_FromString(lock_token);
68 ret = PyObject_CallMethod(self, "link_path", "sslbO", path, url, revision, start_empty, py_lock_token);
69 CB_CHECK_PYRETVAL(ret);
70 PyGILState_Release(state);
74 static svn_error_t *py_ra_report_finish(void *baton, apr_pool_t *pool)
76 PyObject *self = (PyObject *)baton, *ret;
77 PyGILState_STATE state = PyGILState_Ensure();
78 ret = PyObject_CallMethod(self, "finish", "");
79 CB_CHECK_PYRETVAL(ret);
80 PyGILState_Release(state);
84 static svn_error_t *py_ra_report_abort(void *baton, apr_pool_t *pool)
86 PyObject *self = (PyObject *)baton, *ret;
87 PyGILState_STATE state = PyGILState_Ensure();
88 ret = PyObject_CallMethod(self, "abort", "");
89 CB_CHECK_PYRETVAL(ret);
90 PyGILState_Release(state);
94 static const svn_ra_reporter2_t py_ra_reporter = {
95 py_ra_report_set_path,
96 py_ra_report_delete_path,
97 py_ra_report_link_path,
105 * Get libsvn_wc version information.
107 * :return: tuple with major, minor, patch version number and tag.
109 static PyObject *version(PyObject *self)
111 const svn_version_t *ver = svn_wc_version();
112 return Py_BuildValue("(iiis)", ver->major, ver->minor,
113 ver->patch, ver->tag);
116 static svn_error_t *py_wc_found_entry(const char *path, const svn_wc_entry_t *entry, void *walk_baton, apr_pool_t *pool)
118 PyObject *fn = (PyObject *)walk_baton, *ret;
119 PyGILState_STATE state = PyGILState_Ensure();
120 ret = PyObject_CallFunction(fn, "sO", path, py_entry(entry));
121 CB_CHECK_PYRETVAL(ret);
122 PyGILState_Release(state);
126 static svn_wc_entry_callbacks_t py_wc_entry_callbacks = {
130 void py_wc_notify_func(void *baton, const svn_wc_notify_t *notify, apr_pool_t *pool)
132 PyObject *func = baton, *ret;
136 if (notify->err != NULL) {
137 ret = PyObject_CallFunction(func, "O", PyErr_NewSubversionException(notify->err));
139 /* FIXME: Use return value */
146 svn_wc_entry_t entry;
149 static void entry_dealloc(PyObject *self)
151 apr_pool_destroy(((EntryObject *)self)->pool);
155 static PyMemberDef entry_members[] = {
156 { "name", T_STRING, offsetof(EntryObject, entry.name), READONLY, NULL },
157 { "copyfrom_url", T_STRING, offsetof(EntryObject, entry.copyfrom_url), READONLY, NULL },
158 { "copyfrom_rev", T_LONG, offsetof(EntryObject, entry.copyfrom_rev), READONLY, NULL },
159 { "url", T_STRING, offsetof(EntryObject, entry.url), READONLY, NULL },
160 { "repos", T_STRING, offsetof(EntryObject, entry.repos), READONLY, NULL },
161 { "schedule", T_INT, offsetof(EntryObject, entry.schedule), READONLY, NULL },
162 { "kind", T_INT, offsetof(EntryObject, entry.kind), READONLY, NULL },
163 { "revision", T_LONG, offsetof(EntryObject, entry.revision), READONLY, NULL },
164 { "cmt_rev", T_LONG, offsetof(EntryObject, entry.cmt_rev), READONLY, NULL },
165 { "checksum", T_STRING, offsetof(EntryObject, entry.checksum), READONLY, NULL },
166 { "cmt_date", T_LONG, offsetof(EntryObject, entry.cmt_date), READONLY, NULL },
167 { "cmt_author", T_STRING, offsetof(EntryObject, entry.cmt_author), READONLY, NULL },
171 PyTypeObject Entry_Type = {
172 PyObject_HEAD_INIT(NULL) 0,
173 "wc.Entry", /* const char *tp_name; For printing, in format "<module>.<name>" */
175 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
177 /* Methods to implement standard operations */
179 entry_dealloc, /* destructor tp_dealloc; */
180 NULL, /* printfunc tp_print; */
181 NULL, /* getattrfunc tp_getattr; */
182 NULL, /* setattrfunc tp_setattr; */
183 NULL, /* cmpfunc tp_compare; */
184 NULL, /* reprfunc tp_repr; */
186 /* Method suites for standard classes */
188 NULL, /* PyNumberMethods *tp_as_number; */
189 NULL, /* PySequenceMethods *tp_as_sequence; */
190 NULL, /* PyMappingMethods *tp_as_mapping; */
192 /* More standard operations (here for binary compatibility) */
194 NULL, /* hashfunc tp_hash; */
195 NULL, /* ternaryfunc tp_call; */
196 NULL, /* reprfunc tp_str; */
197 NULL, /* getattrofunc tp_getattro; */
198 NULL, /* setattrofunc tp_setattro; */
200 /* Functions to access object as input/output buffer */
201 NULL, /* PyBufferProcs *tp_as_buffer; */
203 /* Flags to define presence of optional/expanded features */
204 0, /* long tp_flags; */
206 NULL, /* const char *tp_doc; Documentation string */
208 /* Assigned meaning in release 2.0 */
209 /* call function for all accessible objects */
210 NULL, /* traverseproc tp_traverse; */
212 /* delete references to contained objects */
213 NULL, /* inquiry tp_clear; */
215 /* Assigned meaning in release 2.1 */
216 /* rich comparisons */
217 NULL, /* richcmpfunc tp_richcompare; */
219 /* weak reference enabler */
220 0, /* Py_ssize_t tp_weaklistoffset; */
222 /* Added in release 2.2 */
224 NULL, /* getiterfunc tp_iter; */
225 NULL, /* iternextfunc tp_iternext; */
227 /* Attribute descriptor and subclassing stuff */
228 NULL, /* struct PyMethodDef *tp_methods; */
229 entry_members, /* struct PyMemberDef *tp_members; */
233 static PyObject *py_entry(const svn_wc_entry_t *entry)
235 EntryObject *ret = PyObject_New(EntryObject, &Entry_Type);
239 ret->pool = Pool(NULL);
240 if (ret->pool == NULL)
242 ret->entry = *svn_wc_entry_dup(entry, ret->pool);
243 return (PyObject *)ret;
248 svn_wc_adm_access_t *adm;
252 static PyObject *adm_init(PyTypeObject *self, PyObject *args, PyObject *kwargs)
254 PyObject *associated;
256 bool write_lock=false;
258 PyObject *cancel_func=Py_None;
259 svn_wc_adm_access_t *parent_wc;
262 char *kwnames[] = { "associated", "path", "write_lock", "depth", "cancel_func", NULL };
264 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os|biO", kwnames, &associated, &path, &write_lock, &depth, &cancel_func))
267 ret = PyObject_New(AdmObject, &Adm_Type);
271 ret->pool = Pool(NULL);
272 if (ret->pool == NULL)
274 if (associated == Py_None) {
277 parent_wc = ((AdmObject *)associated)->adm;
279 Py_BEGIN_ALLOW_THREADS
280 err = svn_wc_adm_open3(&ret->adm, parent_wc, path,
281 write_lock, depth, py_cancel_func, cancel_func,
285 if (!check_error(err)) {
289 return (PyObject *)ret;
292 static PyObject *adm_access_path(PyObject *self)
294 AdmObject *admobj = (AdmObject *)self;
295 return PyString_FromString(svn_wc_adm_access_path(admobj->adm));
298 static PyObject *adm_locked(PyObject *self)
300 AdmObject *admobj = (AdmObject *)self;
301 return PyBool_FromLong(svn_wc_adm_locked(admobj->adm));
304 static PyObject *adm_prop_get(PyObject *self, PyObject *args)
307 AdmObject *admobj = (AdmObject *)self;
308 const svn_string_t *value;
309 apr_pool_t *temp_pool;
312 if (!PyArg_ParseTuple(args, "ss", &name, &path))
315 temp_pool = Pool(NULL);
316 if (temp_pool == NULL)
318 RUN_SVN_WITH_POOL(temp_pool, svn_wc_prop_get(&value, name, path, admobj->adm, temp_pool));
319 if (value == NULL || value->data == NULL) {
322 ret = PyString_FromStringAndSize(value->data, value->len);
324 apr_pool_destroy(temp_pool);
328 static PyObject *adm_prop_set(PyObject *self, PyObject *args)
330 char *name, *value, *path;
331 AdmObject *admobj = (AdmObject *)self;
332 bool skip_checks=false;
333 apr_pool_t *temp_pool;
335 svn_string_t *cvalue;
337 if (!PyArg_ParseTuple(args, "ss#s|b", &name, &value, &vallen, &path, &skip_checks))
340 temp_pool = Pool(NULL);
341 if (temp_pool == NULL)
343 cvalue = svn_string_ncreate(value, vallen, temp_pool);
344 RUN_SVN_WITH_POOL(temp_pool, svn_wc_prop_set2(name, cvalue, path, admobj->adm,
345 skip_checks, temp_pool));
346 apr_pool_destroy(temp_pool);
351 static PyObject *adm_entries_read(PyObject *self, PyObject *args)
354 AdmObject *admobj = (AdmObject *)self;
355 apr_pool_t *temp_pool;
356 bool show_hidden=false;
357 apr_hash_index_t *idx;
360 svn_wc_entry_t *entry;
361 PyObject *py_entries;
363 if (!PyArg_ParseTuple(args, "|b", &show_hidden))
366 temp_pool = Pool(NULL);
367 if (temp_pool == NULL)
369 RUN_SVN_WITH_POOL(temp_pool, svn_wc_entries_read(&entries, admobj->adm,
370 show_hidden, temp_pool));
371 py_entries = PyDict_New();
372 idx = apr_hash_first(temp_pool, entries);
373 while (idx != NULL) {
374 apr_hash_this(idx, (const void **)&key, &klen, (void **)&entry);
375 PyDict_SetItemString(py_entries, key, py_entry(entry));
376 idx = apr_hash_next(idx);
378 apr_pool_destroy(temp_pool);
382 static PyObject *adm_walk_entries(PyObject *self, PyObject *args)
386 bool show_hidden=false;
387 PyObject *cancel_func=Py_None;
388 apr_pool_t *temp_pool;
389 AdmObject *admobj = (AdmObject *)self;
391 if (!PyArg_ParseTuple(args, "sO|bO", &path, &callbacks, &show_hidden, &cancel_func))
394 temp_pool = Pool(NULL);
395 if (temp_pool == NULL)
397 RUN_SVN_WITH_POOL(temp_pool, svn_wc_walk_entries2(path, admobj->adm,
398 &py_wc_entry_callbacks, (void *)callbacks,
399 show_hidden, py_cancel_func, (void *)cancel_func,
401 apr_pool_destroy(temp_pool);
406 static PyObject *adm_entry(PyObject *self, PyObject *args)
409 bool show_hidden=false;
410 apr_pool_t *temp_pool;
411 AdmObject *admobj = (AdmObject *)self;
412 const svn_wc_entry_t *entry;
414 if (!PyArg_ParseTuple(args, "s|b", &path, &show_hidden))
417 temp_pool = Pool(NULL);
418 if (temp_pool == NULL)
420 RUN_SVN_WITH_POOL(temp_pool, svn_wc_entry(&entry, path, admobj->adm, show_hidden, temp_pool));
421 apr_pool_destroy(temp_pool);
423 return py_entry(entry);
426 static PyObject *adm_get_prop_diffs(PyObject *self, PyObject *args)
429 apr_pool_t *temp_pool;
430 apr_array_header_t *propchanges;
431 apr_hash_t *original_props;
432 AdmObject *admobj = (AdmObject *)self;
435 PyObject *py_propchanges, *py_orig_props, *pyval;
437 if (!PyArg_ParseTuple(args, "s", &path))
440 temp_pool = Pool(NULL);
441 if (temp_pool == NULL)
443 RUN_SVN_WITH_POOL(temp_pool, svn_wc_get_prop_diffs(&propchanges, &original_props,
444 svn_path_canonicalize(path, temp_pool), admobj->adm, temp_pool));
445 py_propchanges = PyList_New(propchanges->nelts);
446 for (i = 0; i < propchanges->nelts; i++) {
447 el = APR_ARRAY_IDX(propchanges, i, svn_prop_t);
448 pyval = Py_BuildValue("(ss#)", el.name, el.value->data, el.value->len);
450 apr_pool_destroy(temp_pool);
453 PyList_SetItem(py_propchanges, i, pyval);
455 py_orig_props = prop_hash_to_dict(original_props);
456 apr_pool_destroy(temp_pool);
457 if (py_orig_props == NULL)
459 return Py_BuildValue("(NN)", py_propchanges, py_orig_props);
462 static PyObject *adm_add(PyObject *self, PyObject *args)
464 char *path, *copyfrom_url=NULL;
465 svn_revnum_t copyfrom_rev=-1;
466 PyObject *cancel_func=Py_None, *notify_func=Py_None;
467 AdmObject *admobj = (AdmObject *)self;
468 apr_pool_t *temp_pool;
470 temp_pool = Pool(NULL);
471 if (temp_pool == NULL)
474 if (!PyArg_ParseTuple(args, "s|zlOO", &path, ©from_url, ©from_rev, &cancel_func, ¬ify_func))
477 RUN_SVN_WITH_POOL(temp_pool, svn_wc_add2(path, admobj->adm, copyfrom_url,
478 copyfrom_rev, py_cancel_func,
483 apr_pool_destroy(temp_pool);
488 static PyObject *adm_copy(PyObject *self, PyObject *args)
490 AdmObject *admobj = (AdmObject *)self;
492 PyObject *cancel_func=Py_None, *notify_func=Py_None;
493 apr_pool_t *temp_pool;
495 if (!PyArg_ParseTuple(args, "ss|OO", &src, &dst, &cancel_func, ¬ify_func))
498 temp_pool = Pool(NULL);
499 if (temp_pool == NULL)
501 RUN_SVN_WITH_POOL(temp_pool, svn_wc_copy2(src, admobj->adm, dst,
502 py_cancel_func, (void *)cancel_func,
503 py_wc_notify_func, (void *)notify_func,
505 apr_pool_destroy(temp_pool);
510 static PyObject *adm_delete(PyObject *self, PyObject *args)
512 AdmObject *admobj = (AdmObject *)self;
513 apr_pool_t *temp_pool;
515 PyObject *cancel_func=Py_None, *notify_func=Py_None;
517 if (!PyArg_ParseTuple(args, "s|OO", &path, &cancel_func, ¬ify_func))
520 temp_pool = Pool(NULL);
521 if (temp_pool == NULL)
523 RUN_SVN_WITH_POOL(temp_pool, svn_wc_delete2(path, admobj->adm,
524 py_cancel_func, (void *)cancel_func,
525 py_wc_notify_func, (void *)notify_func,
527 apr_pool_destroy(temp_pool);
532 static PyObject *adm_crawl_revisions(PyObject *self, PyObject *args, PyObject *kwargs)
536 bool restore_files=true, recurse=true, use_commit_times=true;
537 PyObject *notify_func=Py_None;
538 apr_pool_t *temp_pool;
539 AdmObject *admobj = (AdmObject *)self;
540 svn_wc_traversal_info_t *traversal_info;
541 char *kwnames[] = { "path", "reporter", "restore_files", "recurse", "use_commit_times", "notify_func", NULL };
543 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|bbbO", kwnames, &path, &reporter, &restore_files, &recurse, &use_commit_times,
547 temp_pool = Pool(NULL);
548 if (temp_pool == NULL)
550 traversal_info = svn_wc_init_traversal_info(temp_pool);
551 RUN_SVN_WITH_POOL(temp_pool, svn_wc_crawl_revisions2(path, admobj->adm,
552 &py_ra_reporter, (void *)reporter,
553 restore_files, recurse, use_commit_times,
554 py_wc_notify_func, (void *)notify_func,
555 traversal_info, temp_pool));
556 apr_pool_destroy(temp_pool);
561 static PyObject *adm_get_update_editor(PyObject *self, PyObject *args)
564 bool use_commit_times=true, recurse=true;
565 PyObject * notify_func=Py_None, *cancel_func=Py_None;
566 char *diff3_cmd=NULL;
567 const svn_delta_editor_t *editor;
568 AdmObject *admobj = (AdmObject *)self;
571 svn_revnum_t *latest_revnum;
573 if (!PyArg_ParseTuple(args, "s|bbOOz", &target, &use_commit_times, &recurse, ¬ify_func, &cancel_func, &diff3_cmd))
579 latest_revnum = (svn_revnum_t *)apr_palloc(pool, sizeof(svn_revnum_t));
580 Py_BEGIN_ALLOW_THREADS
581 if (!check_error(svn_wc_get_update_editor2(latest_revnum, admobj->adm, target,
582 use_commit_times, recurse, py_wc_notify_func, (void *)notify_func,
583 py_cancel_func, (void *)cancel_func, diff3_cmd, &editor, &edit_baton,
585 apr_pool_destroy(pool);
586 PyEval_RestoreThread(_save);
590 return new_editor_object(editor, edit_baton, pool, &Editor_Type, NULL, NULL);
593 static bool py_dict_to_wcprop_changes(PyObject *dict, apr_pool_t *pool, apr_array_header_t **ret)
598 if (dict == Py_None) {
603 if (!PyDict_Check(dict)) {
604 PyErr_SetString(PyExc_TypeError, "Expected dictionary with property changes");
608 *ret = apr_array_make(pool, PyDict_Size(dict), sizeof(char *));
610 while (PyDict_Next(dict, &idx, &key, &val)) {
611 svn_prop_t *prop = apr_palloc(pool, sizeof(svn_prop_t));
612 prop->name = PyString_AsString(key);
613 if (val == Py_None) {
616 prop->value = svn_string_ncreate(PyString_AsString(val), PyString_Size(val), pool);
618 APR_ARRAY_PUSH(*ret, svn_prop_t *) = prop;
624 static PyObject *adm_process_committed(PyObject *self, PyObject *args, PyObject *kwargs)
626 char *path, *rev_date, *rev_author;
627 bool recurse, remove_lock = false;
628 unsigned char *digest = NULL;
629 svn_revnum_t new_revnum;
630 PyObject *py_wcprop_changes = Py_None;
631 apr_array_header_t *wcprop_changes;
632 AdmObject *admobj = (AdmObject *)self;
633 apr_pool_t *temp_pool;
634 char *kwnames[] = { "path", "recurse", "new_revnum", "rev_date", "rev_author",
635 "wcprop_changes", "remove_lock", "digest", NULL };
637 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sblss|Obs", kwnames,
638 &path, &recurse, &new_revnum, &rev_date,
639 &rev_author, &py_wcprop_changes,
640 &remove_lock, &digest))
643 temp_pool = Pool(NULL);
644 if (temp_pool == NULL)
647 if (!py_dict_to_wcprop_changes(py_wcprop_changes, temp_pool, &wcprop_changes)) {
648 apr_pool_destroy(temp_pool);
652 RUN_SVN_WITH_POOL(temp_pool, svn_wc_process_committed3(path, admobj->adm, recurse, new_revnum,
653 rev_date, rev_author, wcprop_changes,
654 remove_lock, digest, temp_pool));
656 apr_pool_destroy(temp_pool);
661 static PyObject *adm_close(PyObject *self)
663 AdmObject *admobj = (AdmObject *)self;
664 if (admobj->adm != NULL) {
665 Py_BEGIN_ALLOW_THREADS
666 svn_wc_adm_close(admobj->adm);
674 static void adm_dealloc(PyObject *self)
676 apr_pool_destroy(((AdmObject *)self)->pool);
680 static PyMethodDef adm_methods[] = {
681 { "prop_set", adm_prop_set, METH_VARARGS, NULL },
682 { "access_path", (PyCFunction)adm_access_path, METH_NOARGS, NULL },
683 { "prop_get", adm_prop_get, METH_VARARGS, NULL },
684 { "entries_read", adm_entries_read, METH_VARARGS, NULL },
685 { "walk_entries", adm_walk_entries, METH_VARARGS, NULL },
686 { "locked", (PyCFunction)adm_locked, METH_NOARGS, NULL },
687 { "get_prop_diffs", adm_get_prop_diffs, METH_VARARGS, NULL },
688 { "add", adm_add, METH_VARARGS, NULL },
689 { "copy", adm_copy, METH_VARARGS, NULL },
690 { "delete", adm_delete, METH_VARARGS, NULL },
691 { "crawl_revisions", (PyCFunction)adm_crawl_revisions, METH_VARARGS|METH_KEYWORDS, NULL },
692 { "get_update_editor", adm_get_update_editor, METH_VARARGS, NULL },
693 { "close", (PyCFunction)adm_close, METH_NOARGS, NULL },
694 { "entry", (PyCFunction)adm_entry, METH_VARARGS, NULL },
695 { "process_committed", (PyCFunction)adm_process_committed, METH_VARARGS|METH_KEYWORDS, NULL },
699 PyTypeObject Adm_Type = {
700 PyObject_HEAD_INIT(NULL) 0,
701 "wc.WorkingCopy", /* const char *tp_name; For printing, in format "<module>.<name>" */
703 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
705 /* Methods to implement standard operations */
707 adm_dealloc, /* destructor tp_dealloc; */
708 NULL, /* printfunc tp_print; */
709 NULL, /* getattrfunc tp_getattr; */
710 NULL, /* setattrfunc tp_setattr; */
711 NULL, /* cmpfunc tp_compare; */
712 NULL, /* reprfunc tp_repr; */
714 /* Method suites for standard classes */
716 NULL, /* PyNumberMethods *tp_as_number; */
717 NULL, /* PySequenceMethods *tp_as_sequence; */
718 NULL, /* PyMappingMethods *tp_as_mapping; */
720 /* More standard operations (here for binary compatibility) */
722 NULL, /* hashfunc tp_hash; */
723 NULL, /* ternaryfunc tp_call; */
724 NULL, /* reprfunc tp_str; */
725 NULL, /* getattrofunc tp_getattro; */
726 NULL, /* setattrofunc tp_setattro; */
728 /* Functions to access object as input/output buffer */
729 NULL, /* PyBufferProcs *tp_as_buffer; */
731 /* Flags to define presence of optional/expanded features */
732 0, /* long tp_flags; */
734 NULL, /* const char *tp_doc; Documentation string */
736 /* Assigned meaning in release 2.0 */
737 /* call function for all accessible objects */
738 NULL, /* traverseproc tp_traverse; */
740 /* delete references to contained objects */
741 NULL, /* inquiry tp_clear; */
743 /* Assigned meaning in release 2.1 */
744 /* rich comparisons */
745 NULL, /* richcmpfunc tp_richcompare; */
747 /* weak reference enabler */
748 0, /* Py_ssize_t tp_weaklistoffset; */
750 /* Added in release 2.2 */
752 NULL, /* getiterfunc tp_iter; */
753 NULL, /* iternextfunc tp_iternext; */
755 /* Attribute descriptor and subclassing stuff */
756 adm_methods, /* struct PyMethodDef *tp_methods; */
757 NULL, /* struct PyMemberDef *tp_members; */
758 NULL, /* struct PyGetSetDef *tp_getset; */
759 NULL, /* struct _typeobject *tp_base; */
760 NULL, /* PyObject *tp_dict; */
761 NULL, /* descrgetfunc tp_descr_get; */
762 NULL, /* descrsetfunc tp_descr_set; */
763 0, /* Py_ssize_t tp_dictoffset; */
764 NULL, /* initproc tp_init; */
765 NULL, /* allocfunc tp_alloc; */
766 adm_init, /* newfunc tp_new; */
771 * Determine the revision status of a specified working copy.
773 * :return: Tuple with minimum and maximum revnums found, whether the
774 * working copy was switched and whether it was modified.
776 static PyObject *revision_status(PyObject *self, PyObject *args, PyObject *kwargs)
778 char *kwnames[] = { "wc_path", "trail_url", "committed", "cancel_func", NULL };
779 char *wc_path, *trail_url=NULL;
780 bool committed=false;
781 PyObject *cancel_func=Py_None, *ret;
782 svn_wc_revision_status_t *revstatus;
783 apr_pool_t *temp_pool;
785 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zbO", kwnames, &wc_path, &trail_url, &committed,
789 temp_pool = Pool(NULL);
790 if (temp_pool == NULL)
792 RUN_SVN_WITH_POOL(temp_pool, svn_wc_revision_status(&revstatus, wc_path, trail_url,
793 committed, py_cancel_func, cancel_func, temp_pool));
794 ret = Py_BuildValue("(llbb)", revstatus->min_rev, revstatus->max_rev,
795 revstatus->switched, revstatus->modified);
796 apr_pool_destroy(temp_pool);
800 static PyObject *is_normal_prop(PyObject *self, PyObject *args)
804 if (!PyArg_ParseTuple(args, "s", &name))
807 return PyBool_FromLong(svn_wc_is_normal_prop(name));
810 static PyObject *is_adm_dir(PyObject *self, PyObject *args)
816 if (!PyArg_ParseTuple(args, "s", &name))
823 ret = svn_wc_is_adm_dir(name, pool);
825 apr_pool_destroy(pool);
827 return PyBool_FromLong(ret);
830 static PyObject *is_wc_prop(PyObject *self, PyObject *args)
834 if (!PyArg_ParseTuple(args, "s", &name))
837 return PyBool_FromLong(svn_wc_is_wc_prop(name));
840 static PyObject *is_entry_prop(PyObject *self, PyObject *args)
844 if (!PyArg_ParseTuple(args, "s", &name))
847 return PyBool_FromLong(svn_wc_is_entry_prop(name));
850 static PyObject *get_adm_dir(PyObject *self)
858 dir = svn_wc_get_adm_dir(pool);
859 ret = PyString_FromString(dir);
860 apr_pool_destroy(pool);
864 static PyObject *get_pristine_copy_path(PyObject *self, PyObject *args)
867 const char *pristine_path;
871 if (!PyArg_ParseTuple(args, "s", &path))
877 RUN_SVN_WITH_POOL(pool, svn_wc_get_pristine_copy_path(path, &pristine_path, pool));
878 ret = PyString_FromString(pristine_path);
879 apr_pool_destroy(pool);
883 static PyObject *ensure_adm(PyObject *self, PyObject *args, PyObject *kwargs)
885 char *path, *uuid, *url;
889 char *kwnames[] = { "path", "uuid", "url", "repos", "rev", NULL };
891 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|sl", kwnames,
892 &path, &uuid, &url, &repos, &rev))
898 RUN_SVN_WITH_POOL(pool,
899 svn_wc_ensure_adm2(path, uuid, url, repos, rev, pool));
900 apr_pool_destroy(pool);
904 static PyObject *check_wc(PyObject *self, PyObject *args)
910 if (!PyArg_ParseTuple(args, "s", &path))
916 RUN_SVN_WITH_POOL(pool, svn_wc_check_wc(path, &wc_format, pool));
917 apr_pool_destroy(pool);
918 return PyLong_FromLong(wc_format);
921 static PyMethodDef wc_methods[] = {
922 { "check_wc", check_wc, METH_VARARGS, NULL },
923 { "ensure_adm", (PyCFunction)ensure_adm, METH_KEYWORDS|METH_VARARGS, NULL },
924 { "get_adm_dir", (PyCFunction)get_adm_dir, METH_NOARGS, NULL },
925 { "get_pristine_copy_path", get_pristine_copy_path, METH_VARARGS, NULL },
926 { "is_adm_dir", is_adm_dir, METH_VARARGS, NULL },
927 { "is_normal_prop", is_normal_prop, METH_VARARGS, NULL },
928 { "is_entry_prop", is_entry_prop, METH_VARARGS, NULL },
929 { "is_wc_prop", is_wc_prop, METH_VARARGS, NULL },
930 { "revision_status", (PyCFunction)revision_status, METH_KEYWORDS|METH_VARARGS, NULL },
931 { "version", (PyCFunction)version, METH_NOARGS, NULL },
939 if (PyType_Ready(&Entry_Type) < 0)
942 if (PyType_Ready(&Adm_Type) < 0)
945 if (PyType_Ready(&Editor_Type) < 0)
948 if (PyType_Ready(&FileEditor_Type) < 0)
951 if (PyType_Ready(&DirectoryEditor_Type) < 0)
954 if (PyType_Ready(&TxDeltaWindowHandler_Type) < 0)
959 mod = Py_InitModule3("wc", wc_methods, "Working Copies");
963 PyModule_AddIntConstant(mod, "SCHEDULE_NORMAL", 0);
964 PyModule_AddIntConstant(mod, "SCHEDULE_ADD", 1);
965 PyModule_AddIntConstant(mod, "SCHEDULE_DELETE", 2);
966 PyModule_AddIntConstant(mod, "SCHEDULE_REPLACE", 3);
968 PyModule_AddObject(mod, "WorkingCopy", (PyObject *)&Adm_Type);
969 Py_INCREF(&Adm_Type);