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
20 #include <apr_general.h>
23 #include <svn_props.h>
24 #include <structmember.h>
31 #if ONLY_SINCE_SVN(1, 5)
32 #define REPORTER_T svn_ra_reporter3_t
34 #define REPORTER_T svn_ra_reporter2_t
37 staticforward PyTypeObject Entry_Type;
38 staticforward PyTypeObject Adm_Type;
40 static PyObject *py_entry(const svn_wc_entry_t *entry);
42 #if ONLY_BEFORE_SVN(1, 5)
43 struct svn_wc_committed_queue_t
46 apr_array_header_t *queue;
47 svn_boolean_t have_recursive;
51 typedef struct svn_wc_committed_queue_t svn_wc_committed_queue_t;
57 svn_wc_adm_access_t *adm_access;
58 svn_boolean_t recurse;
59 svn_boolean_t remove_lock;
60 apr_array_header_t *wcprop_changes;
61 unsigned char *digest;
62 } committed_queue_item_t;
67 svn_wc_committed_queue_t *svn_wc_committed_queue_create(apr_pool_t *pool)
69 svn_wc_committed_queue_t *q;
71 q = apr_palloc(pool, sizeof(*q));
73 q->queue = apr_array_make(pool, 1, sizeof(committed_queue_item_t *));
74 q->have_recursive = FALSE;
82 svn_error_t *svn_wc_queue_committed(svn_wc_committed_queue_t **queue,
84 svn_wc_adm_access_t *adm_access,
85 svn_boolean_t recurse,
86 apr_array_header_t *wcprop_changes,
87 svn_boolean_t remove_lock,
88 svn_boolean_t remove_changelist,
89 const unsigned char *digest,
90 apr_pool_t *scratch_pool)
92 committed_queue_item_t *cqi;
94 (*queue)->have_recursive |= recurse;
96 /* Use the same pool as the one QUEUE was allocated in,
97 to prevent lifetime issues. Intermediate operations
98 should use SCRATCH_POOL. */
100 /* Add to the array with paths and options */
101 cqi = apr_palloc((*queue)->pool, sizeof(*cqi));
103 cqi->adm_access = adm_access;
104 cqi->recurse = recurse;
105 cqi->remove_lock = remove_lock;
106 cqi->wcprop_changes = wcprop_changes;
107 cqi->digest = digest;
109 APR_ARRAY_PUSH((*queue)->queue, committed_queue_item_t *) = cqi;
119 svn_wc_committed_queue_t *queue;
120 } CommittedQueueObject;
121 staticforward PyTypeObject CommittedQueue_Type;
123 #if ONLY_SINCE_SVN(1, 5)
124 static svn_error_t *py_ra_report_set_path(void *baton, const char *path, svn_revnum_t revision, svn_depth_t depth, int start_empty, const char *lock_token, apr_pool_t *pool)
126 PyObject *self = (PyObject *)baton, *py_lock_token, *ret;
127 PyGILState_STATE state = PyGILState_Ensure();
128 if (lock_token == NULL) {
129 py_lock_token = Py_None;
130 Py_INCREF(py_lock_token);
132 py_lock_token = PyString_FromString(lock_token);
134 ret = PyObject_CallMethod(self, "set_path", "slbOi", path, revision, start_empty, py_lock_token, depth);
135 Py_DECREF(py_lock_token);
136 CB_CHECK_PYRETVAL(ret);
138 PyGILState_Release(state);
142 static svn_error_t *py_ra_report_link_path(void *report_baton, const char *path, const char *url, svn_revnum_t revision, svn_depth_t depth, int start_empty, const char *lock_token, apr_pool_t *pool)
144 PyObject *self = (PyObject *)report_baton, *ret, *py_lock_token;
145 PyGILState_STATE state = PyGILState_Ensure();
146 if (lock_token == NULL) {
147 py_lock_token = Py_None;
148 Py_INCREF(py_lock_token);
150 py_lock_token = PyString_FromString(lock_token);
152 ret = PyObject_CallMethod(self, "link_path", "sslbOi", path, url, revision, start_empty, py_lock_token, depth);
153 Py_DECREF(py_lock_token);
154 CB_CHECK_PYRETVAL(ret);
156 PyGILState_Release(state);
162 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)
164 PyObject *self = (PyObject *)baton, *py_lock_token, *ret;
165 PyGILState_STATE state = PyGILState_Ensure();
166 if (lock_token == NULL) {
167 py_lock_token = Py_None;
168 Py_INCREF(py_lock_token);
170 py_lock_token = PyString_FromString(lock_token);
172 ret = PyObject_CallMethod(self, "set_path", "slbOi", path, revision, start_empty, py_lock_token, svn_depth_infinity);
173 CB_CHECK_PYRETVAL(ret);
175 PyGILState_Release(state);
179 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)
181 PyObject *self = (PyObject *)report_baton, *ret, *py_lock_token;
182 PyGILState_STATE state = PyGILState_Ensure();
183 if (lock_token == NULL) {
184 py_lock_token = Py_None;
185 Py_INCREF(py_lock_token);
187 py_lock_token = PyString_FromString(lock_token);
189 ret = PyObject_CallMethod(self, "link_path", "sslbOi", path, url, revision, start_empty, py_lock_token, svn_depth_infinity);
190 CB_CHECK_PYRETVAL(ret);
192 PyGILState_Release(state);
199 static svn_error_t *py_ra_report_delete_path(void *baton, const char *path, apr_pool_t *pool)
201 PyObject *self = (PyObject *)baton, *ret;
202 PyGILState_STATE state = PyGILState_Ensure();
203 ret = PyObject_CallMethod(self, "delete_path", "s", path);
204 CB_CHECK_PYRETVAL(ret);
206 PyGILState_Release(state);
210 static svn_error_t *py_ra_report_finish(void *baton, apr_pool_t *pool)
212 PyObject *self = (PyObject *)baton, *ret;
213 PyGILState_STATE state = PyGILState_Ensure();
214 ret = PyObject_CallMethod(self, "finish", "");
215 CB_CHECK_PYRETVAL(ret);
217 PyGILState_Release(state);
221 static svn_error_t *py_ra_report_abort(void *baton, apr_pool_t *pool)
223 PyObject *self = (PyObject *)baton, *ret;
224 PyGILState_STATE state = PyGILState_Ensure();
225 ret = PyObject_CallMethod(self, "abort", "");
226 CB_CHECK_PYRETVAL(ret);
228 PyGILState_Release(state);
232 static const REPORTER_T py_ra_reporter = {
233 py_ra_report_set_path,
234 py_ra_report_delete_path,
235 py_ra_report_link_path,
243 * Get runtime libsvn_wc version information.
245 * :return: tuple with major, minor, patch version number and tag.
247 static PyObject *version(PyObject *self)
249 const svn_version_t *ver = svn_wc_version();
250 return Py_BuildValue("(iiis)", ver->major, ver->minor,
251 ver->patch, ver->tag);
254 SVN_VERSION_DEFINE(svn_api_version);
257 * Get compile-time libsvn_wc version information.
259 * :return: tuple with major, minor, patch version number and tag.
261 static PyObject *api_version(PyObject *self)
263 const svn_version_t *ver = &svn_api_version;
264 return Py_BuildValue("(iiis)", ver->major, ver->minor,
265 ver->patch, ver->tag);
268 static svn_error_t *py_wc_found_entry(const char *path, const svn_wc_entry_t *entry, void *walk_baton, apr_pool_t *pool)
271 PyObject *callbacks = (PyObject *)walk_baton;
272 PyGILState_STATE state = PyGILState_Ensure();
273 if (PyTuple_Check(callbacks)) {
274 fn = PyTuple_GET_ITEM(callbacks, 0);
276 fn = (PyObject *)walk_baton;
278 ret = PyObject_CallFunction(fn, "sO", path, py_entry(entry));
279 CB_CHECK_PYRETVAL(ret);
281 PyGILState_Release(state);
285 #if ONLY_SINCE_SVN(1, 5)
287 svn_error_t *py_wc_handle_error(const char *path, svn_error_t *err, void *walk_baton, apr_pool_t *pool)
291 PyGILState_STATE state;
292 PyObject *callbacks = (PyObject *)walk_baton;
293 if (PyTuple_Check(callbacks)) {
294 fn = PyTuple_GET_ITEM(callbacks, 1);
298 state = PyGILState_Ensure();
299 py_err = PyErr_NewSubversionException(err);
300 ret = PyObject_CallFunction(fn, "sO", path, py_err);
301 CB_CHECK_PYRETVAL(ret);
303 PyGILState_Release(state);
308 static svn_wc_entry_callbacks2_t py_wc_entry_callbacks2 = {
313 static svn_wc_entry_callbacks_t py_wc_entry_callbacks = {
320 void py_wc_notify_func(void *baton, const svn_wc_notify_t *notify, apr_pool_t *pool)
322 PyObject *func = baton, *ret;
326 if (notify->err != NULL) {
327 PyObject *excval = PyErr_NewSubversionException(notify->err);
328 ret = PyObject_CallFunction(func, "O", excval);
331 /* FIXME: Use return value */
338 svn_wc_entry_t entry;
341 static void entry_dealloc(PyObject *self)
343 apr_pool_destroy(((EntryObject *)self)->pool);
347 static PyMemberDef entry_members[] = {
348 { "name", T_STRING, offsetof(EntryObject, entry.name), READONLY,
350 { "copyfrom_url", T_STRING, offsetof(EntryObject, entry.copyfrom_url), READONLY,
351 "Copyfrom location" },
352 { "copyfrom_rev", T_LONG, offsetof(EntryObject, entry.copyfrom_rev), READONLY,
353 "Copyfrom revision" },
354 { "uuid", T_STRING, offsetof(EntryObject, entry.uuid), READONLY,
355 "UUID of repository" },
356 { "url", T_STRING, offsetof(EntryObject, entry.url), READONLY,
357 "URL in repository" },
358 { "repos", T_STRING, offsetof(EntryObject, entry.repos), READONLY,
359 "Canonical repository URL" },
360 { "schedule", T_INT, offsetof(EntryObject, entry.schedule), READONLY,
361 "Scheduling (add, replace, delete, etc)" },
362 { "kind", T_INT, offsetof(EntryObject, entry.kind), READONLY,
363 "Kind of file (file, dir, etc)" },
364 { "revision", T_LONG, offsetof(EntryObject, entry.revision), READONLY,
366 { "cmt_rev", T_LONG, offsetof(EntryObject, entry.cmt_rev), READONLY,
367 "Last revision this was changed" },
368 { "checksum", T_STRING, offsetof(EntryObject, entry.checksum), READONLY,
369 "Hex MD5 checksum for the untranslated text base file" },
370 { "cmt_date", T_LONG, offsetof(EntryObject, entry.cmt_date), READONLY,
371 "Last date this was changed" },
372 { "cmt_author", T_STRING, offsetof(EntryObject, entry.cmt_author), READONLY,
373 "Last commit author of this item" },
377 static PyTypeObject Entry_Type = {
378 PyObject_HEAD_INIT(NULL) 0,
379 "wc.Entry", /* const char *tp_name; For printing, in format "<module>.<name>" */
381 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
383 /* Methods to implement standard operations */
385 entry_dealloc, /* destructor tp_dealloc; */
386 NULL, /* printfunc tp_print; */
387 NULL, /* getattrfunc tp_getattr; */
388 NULL, /* setattrfunc tp_setattr; */
389 NULL, /* cmpfunc tp_compare; */
390 NULL, /* reprfunc tp_repr; */
392 /* Method suites for standard classes */
394 NULL, /* PyNumberMethods *tp_as_number; */
395 NULL, /* PySequenceMethods *tp_as_sequence; */
396 NULL, /* PyMappingMethods *tp_as_mapping; */
398 /* More standard operations (here for binary compatibility) */
400 NULL, /* hashfunc tp_hash; */
401 NULL, /* ternaryfunc tp_call; */
402 NULL, /* reprfunc tp_str; */
403 NULL, /* getattrofunc tp_getattro; */
404 NULL, /* setattrofunc tp_setattro; */
406 /* Functions to access object as input/output buffer */
407 NULL, /* PyBufferProcs *tp_as_buffer; */
409 /* Flags to define presence of optional/expanded features */
410 0, /* long tp_flags; */
412 NULL, /* const char *tp_doc; Documentation string */
414 /* Assigned meaning in release 2.0 */
415 /* call function for all accessible objects */
416 NULL, /* traverseproc tp_traverse; */
418 /* delete references to contained objects */
419 NULL, /* inquiry tp_clear; */
421 /* Assigned meaning in release 2.1 */
422 /* rich comparisons */
423 NULL, /* richcmpfunc tp_richcompare; */
425 /* weak reference enabler */
426 0, /* Py_ssize_t tp_weaklistoffset; */
428 /* Added in release 2.2 */
430 NULL, /* getiterfunc tp_iter; */
431 NULL, /* iternextfunc tp_iternext; */
433 /* Attribute descriptor and subclassing stuff */
434 NULL, /* struct PyMethodDef *tp_methods; */
435 entry_members, /* struct PyMemberDef *tp_members; */
439 static PyObject *py_entry(const svn_wc_entry_t *entry)
443 ret = PyObject_New(EntryObject, &Entry_Type);
447 ret->pool = Pool(NULL);
448 if (ret->pool == NULL)
450 ret->entry = *svn_wc_entry_dup(entry, ret->pool);
451 return (PyObject *)ret;
456 svn_wc_adm_access_t *adm;
460 #define ADM_CHECK_CLOSED(adm_obj) \
461 if (adm_obj->adm == NULL) { \
462 PyErr_SetString(PyExc_RuntimeError, "WorkingCopy instance already closed"); \
466 static PyObject *adm_init(PyTypeObject *self, PyObject *args, PyObject *kwargs)
468 PyObject *associated;
470 bool write_lock=false;
472 PyObject *cancel_func=Py_None;
473 svn_wc_adm_access_t *parent_wc;
476 char *kwnames[] = { "associated", "path", "write_lock", "depth", "cancel_func", NULL };
478 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os|biO", kwnames, &associated, &path, &write_lock, &depth, &cancel_func))
481 ret = PyObject_New(AdmObject, &Adm_Type);
485 ret->pool = Pool(NULL);
486 if (ret->pool == NULL)
488 if (associated == Py_None) {
491 parent_wc = ((AdmObject *)associated)->adm;
493 Py_BEGIN_ALLOW_THREADS
494 err = svn_wc_adm_open3(&ret->adm, parent_wc,
495 svn_path_canonicalize(path, ret->pool),
496 write_lock, depth, py_cancel_func, cancel_func,
500 if (!check_error(err)) {
504 return (PyObject *)ret;
507 static PyObject *adm_access_path(PyObject *self)
509 AdmObject *admobj = (AdmObject *)self;
510 ADM_CHECK_CLOSED(admobj);
511 return PyString_FromString(svn_wc_adm_access_path(admobj->adm));
514 static PyObject *adm_locked(PyObject *self)
516 AdmObject *admobj = (AdmObject *)self;
517 ADM_CHECK_CLOSED(admobj);
518 return PyBool_FromLong(svn_wc_adm_locked(admobj->adm));
521 static PyObject *adm_prop_get(PyObject *self, PyObject *args)
524 AdmObject *admobj = (AdmObject *)self;
525 const svn_string_t *value;
526 apr_pool_t *temp_pool;
529 if (!PyArg_ParseTuple(args, "ss", &name, &path))
532 ADM_CHECK_CLOSED(admobj);
534 temp_pool = Pool(NULL);
535 if (temp_pool == NULL)
537 RUN_SVN_WITH_POOL(temp_pool, svn_wc_prop_get(&value, name, path, admobj->adm, temp_pool));
538 if (value == NULL || value->data == NULL) {
542 ret = PyString_FromStringAndSize(value->data, value->len);
544 apr_pool_destroy(temp_pool);
548 static PyObject *adm_prop_set(PyObject *self, PyObject *args)
550 char *name, *value, *path;
551 AdmObject *admobj = (AdmObject *)self;
552 bool skip_checks=false;
553 apr_pool_t *temp_pool;
555 svn_string_t *cvalue;
556 PyObject *notify_func = Py_None;
558 if (!PyArg_ParseTuple(args, "ss#s|bO", &name, &value, &vallen, &path, &skip_checks,
562 ADM_CHECK_CLOSED(admobj);
564 temp_pool = Pool(NULL);
565 if (temp_pool == NULL)
567 cvalue = svn_string_ncreate(value, vallen, temp_pool);
568 #if ONLY_SINCE_SVN(1, 6)
569 RUN_SVN_WITH_POOL(temp_pool, svn_wc_prop_set3(name, cvalue, path, admobj->adm,
570 skip_checks, py_wc_notify_func, (void *)notify_func,
573 RUN_SVN_WITH_POOL(temp_pool, svn_wc_prop_set2(name, cvalue, path, admobj->adm,
574 skip_checks, temp_pool));
576 apr_pool_destroy(temp_pool);
581 static PyObject *adm_entries_read(PyObject *self, PyObject *args)
584 AdmObject *admobj = (AdmObject *)self;
585 apr_pool_t *temp_pool;
586 bool show_hidden=false;
587 apr_hash_index_t *idx;
590 svn_wc_entry_t *entry;
591 PyObject *py_entries, *obj;
593 if (!PyArg_ParseTuple(args, "|b", &show_hidden))
596 ADM_CHECK_CLOSED(admobj);
598 temp_pool = Pool(NULL);
599 if (temp_pool == NULL)
601 RUN_SVN_WITH_POOL(temp_pool, svn_wc_entries_read(&entries, admobj->adm,
602 show_hidden, temp_pool));
603 py_entries = PyDict_New();
604 if (py_entries == NULL) {
605 apr_pool_destroy(temp_pool);
608 idx = apr_hash_first(temp_pool, entries);
609 while (idx != NULL) {
610 apr_hash_this(idx, (const void **)&key, &klen, (void **)&entry);
615 obj = py_entry(entry);
617 PyDict_SetItemString(py_entries, key, obj);
619 idx = apr_hash_next(idx);
621 apr_pool_destroy(temp_pool);
625 static PyObject *adm_walk_entries(PyObject *self, PyObject *args)
629 bool show_hidden=false;
630 PyObject *cancel_func=Py_None;
631 apr_pool_t *temp_pool;
632 AdmObject *admobj = (AdmObject *)self;
633 svn_depth_t depth = svn_depth_infinity;
635 if (!PyArg_ParseTuple(args, "sO|bOi", &path, &callbacks, &show_hidden, &cancel_func,
639 ADM_CHECK_CLOSED(admobj);
641 temp_pool = Pool(NULL);
642 if (temp_pool == NULL)
644 #if ONLY_SINCE_SVN(1, 5)
645 RUN_SVN_WITH_POOL(temp_pool, svn_wc_walk_entries3(path, admobj->adm,
646 &py_wc_entry_callbacks2, (void *)callbacks,
647 depth, show_hidden, py_cancel_func, (void *)cancel_func,
650 if (depth != svn_depth_infinity) {
651 PyErr_SetString(PyExc_NotImplementedError,
652 "depth != infinity not supported for svn < 1.5");
653 apr_pool_destroy(temp_pool);
656 RUN_SVN_WITH_POOL(temp_pool, svn_wc_walk_entries2(path, admobj->adm,
657 &py_wc_entry_callbacks, (void *)callbacks,
658 show_hidden, py_cancel_func, (void *)cancel_func,
661 apr_pool_destroy(temp_pool);
666 static PyObject *adm_entry(PyObject *self, PyObject *args)
669 bool show_hidden=false;
670 apr_pool_t *temp_pool;
671 AdmObject *admobj = (AdmObject *)self;
672 const svn_wc_entry_t *entry;
675 if (!PyArg_ParseTuple(args, "s|b", &path, &show_hidden))
678 ADM_CHECK_CLOSED(admobj);
680 temp_pool = Pool(NULL);
681 if (temp_pool == NULL)
683 RUN_SVN_WITH_POOL(temp_pool, svn_wc_entry(&entry, svn_path_canonicalize(path, temp_pool), admobj->adm, show_hidden, temp_pool));
686 PyErr_Format(PyExc_KeyError, "No such entry '%s'", path);
689 ret = py_entry(entry);
692 apr_pool_destroy(temp_pool);
696 static PyObject *adm_get_prop_diffs(PyObject *self, PyObject *args)
699 apr_pool_t *temp_pool;
700 apr_array_header_t *propchanges;
701 apr_hash_t *original_props;
702 AdmObject *admobj = (AdmObject *)self;
705 PyObject *py_propchanges, *py_orig_props, *pyval;
707 if (!PyArg_ParseTuple(args, "s", &path))
710 ADM_CHECK_CLOSED(admobj);
712 temp_pool = Pool(NULL);
713 if (temp_pool == NULL)
715 RUN_SVN_WITH_POOL(temp_pool, svn_wc_get_prop_diffs(&propchanges, &original_props,
716 svn_path_canonicalize(path, temp_pool), admobj->adm, temp_pool));
717 py_propchanges = PyList_New(propchanges->nelts);
718 if (py_propchanges == NULL) {
719 apr_pool_destroy(temp_pool);
722 for (i = 0; i < propchanges->nelts; i++) {
723 el = APR_ARRAY_IDX(propchanges, i, svn_prop_t);
724 if (el.value != NULL)
725 pyval = Py_BuildValue("(sz#)", el.name, el.value->data, el.value->len);
727 pyval = Py_BuildValue("(sO)", el.name, Py_None);
729 apr_pool_destroy(temp_pool);
732 PyList_SetItem(py_propchanges, i, pyval);
734 py_orig_props = prop_hash_to_dict(original_props);
735 apr_pool_destroy(temp_pool);
736 if (py_orig_props == NULL)
738 return Py_BuildValue("(NN)", py_propchanges, py_orig_props);
741 static PyObject *adm_add(PyObject *self, PyObject *args, PyObject *kwargs)
743 char *path, *copyfrom_url=NULL;
744 svn_revnum_t copyfrom_rev=-1;
745 char *kwnames[] = { "path", "copyfrom_url", "copyfrom_rev", "cancel_func",
746 "notify_func", "depth", NULL };
747 PyObject *cancel_func=Py_None, *notify_func=Py_None;
748 AdmObject *admobj = (AdmObject *)self;
749 apr_pool_t *temp_pool;
750 svn_depth_t depth = svn_depth_infinity;
752 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zlOOi", kwnames, &path, ©from_url, ©from_rev, &cancel_func, ¬ify_func, &depth))
755 ADM_CHECK_CLOSED(admobj);
757 temp_pool = Pool(NULL);
758 if (temp_pool == NULL)
761 #if ONLY_SINCE_SVN(1, 6)
762 RUN_SVN_WITH_POOL(temp_pool, svn_wc_add3(
763 svn_path_canonicalize(path, temp_pool), admobj->adm, depth, copyfrom_url,
764 copyfrom_rev, py_cancel_func,
770 if (depth != svn_depth_infinity) {
771 PyErr_SetString(PyExc_NotImplementedError, "depth != infinity not supported on svn < 1.6");
772 apr_pool_destroy(temp_pool);
775 RUN_SVN_WITH_POOL(temp_pool, svn_wc_add2(
776 svn_path_canonicalize(path, temp_pool), admobj->adm, copyfrom_url,
777 copyfrom_rev, py_cancel_func,
783 apr_pool_destroy(temp_pool);
788 static PyObject *adm_copy(PyObject *self, PyObject *args)
790 AdmObject *admobj = (AdmObject *)self;
792 PyObject *cancel_func=Py_None, *notify_func=Py_None;
793 apr_pool_t *temp_pool;
795 if (!PyArg_ParseTuple(args, "ss|OO", &src, &dst, &cancel_func, ¬ify_func))
798 ADM_CHECK_CLOSED(admobj);
800 temp_pool = Pool(NULL);
801 if (temp_pool == NULL)
803 RUN_SVN_WITH_POOL(temp_pool, svn_wc_copy2(src, admobj->adm, dst,
804 py_cancel_func, (void *)cancel_func,
805 py_wc_notify_func, (void *)notify_func,
807 apr_pool_destroy(temp_pool);
812 static PyObject *adm_delete(PyObject *self, PyObject *args, PyObject *kwargs)
814 AdmObject *admobj = (AdmObject *)self;
815 apr_pool_t *temp_pool;
816 char *kwnames[] = { "path", "cancel_func", "notify_func", "keep_local",
819 PyObject *cancel_func=Py_None, *notify_func=Py_None;
820 bool keep_local = false;
822 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOb", kwnames,
823 &path, &cancel_func, ¬ify_func,
827 ADM_CHECK_CLOSED(admobj);
829 temp_pool = Pool(NULL);
830 if (temp_pool == NULL)
833 #if ONLY_SINCE_SVN(1, 5)
834 RUN_SVN_WITH_POOL(temp_pool, svn_wc_delete3(path, admobj->adm,
835 py_cancel_func, (void *)cancel_func,
836 py_wc_notify_func, (void *)notify_func,
841 PyErr_SetString(PyExc_NotImplementedError,
842 "keep_local not supported on Subversion < 1.5");
846 RUN_SVN_WITH_POOL(temp_pool, svn_wc_delete2(path, admobj->adm,
847 py_cancel_func, (void *)cancel_func,
848 py_wc_notify_func, (void *)notify_func,
851 apr_pool_destroy(temp_pool);
856 static PyObject *adm_crawl_revisions(PyObject *self, PyObject *args, PyObject *kwargs)
860 bool restore_files=true, recurse=true, use_commit_times=true;
861 PyObject *notify_func=Py_None;
862 apr_pool_t *temp_pool;
863 AdmObject *admobj = (AdmObject *)self;
864 svn_wc_traversal_info_t *traversal_info;
865 svn_boolean_t depth_compatibility_trick = FALSE;
866 svn_boolean_t honor_depth_exclude = FALSE;
867 char *kwnames[] = { "path", "reporter", "restore_files", "recurse", "use_commit_times", "notify_func", "depth_compatibility_trick", "honor_depth_exclude,", NULL };
869 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|bbbObb", kwnames, &path, &reporter, &restore_files, &recurse, &use_commit_times,
870 ¬ify_func, &depth_compatibility_trick, &honor_depth_exclude))
873 ADM_CHECK_CLOSED(admobj);
875 temp_pool = Pool(NULL);
876 if (temp_pool == NULL)
878 traversal_info = svn_wc_init_traversal_info(temp_pool);
879 #if ONLY_SINCE_SVN(1, 6)
880 RUN_SVN_WITH_POOL(temp_pool, svn_wc_crawl_revisions4(path, admobj->adm,
881 &py_ra_reporter, (void *)reporter,
882 restore_files, recurse?svn_depth_infinity:svn_depth_files,
884 depth_compatibility_trick, use_commit_times,
885 py_wc_notify_func, (void *)notify_func,
886 traversal_info, temp_pool));
887 #elif ONLY_SINCE_SVN(1, 5)
888 RUN_SVN_WITH_POOL(temp_pool, svn_wc_crawl_revisions3(path, admobj->adm,
889 &py_ra_reporter, (void *)reporter,
890 restore_files, recurse?svn_depth_infinity:svn_depth_files,
891 depth_compatibility_trick, use_commit_times,
892 py_wc_notify_func, (void *)notify_func,
893 traversal_info, temp_pool));
895 RUN_SVN_WITH_POOL(temp_pool, svn_wc_crawl_revisions2(path, admobj->adm,
896 &py_ra_reporter, (void *)reporter,
897 restore_files, recurse, use_commit_times,
898 py_wc_notify_func, (void *)notify_func,
899 traversal_info, temp_pool));
901 apr_pool_destroy(temp_pool);
906 static PyObject *adm_get_update_editor(PyObject *self, PyObject *args)
909 bool use_commit_times=true, recurse=true;
910 PyObject * notify_func=Py_None, *cancel_func=Py_None;
911 char *diff3_cmd=NULL;
912 const svn_delta_editor_t *editor;
913 AdmObject *admobj = (AdmObject *)self;
916 svn_revnum_t *latest_revnum;
918 svn_boolean_t allow_unver_obstructions = FALSE;
919 svn_boolean_t depth_is_sticky = FALSE;
921 if (!PyArg_ParseTuple(args, "s|bbOOzbb", &target, &use_commit_times, &recurse, ¬ify_func, &cancel_func, &diff3_cmd,
922 &depth_is_sticky, &allow_unver_obstructions))
925 ADM_CHECK_CLOSED(admobj);
930 latest_revnum = (svn_revnum_t *)apr_palloc(pool, sizeof(svn_revnum_t));
931 Py_BEGIN_ALLOW_THREADS
932 #if ONLY_SINCE_SVN(1, 5)
933 /* FIXME: Support all values of depth */
934 /* FIXME: Support fetch_func */
935 /* FIXME: Support conflict func */
936 err = svn_wc_get_update_editor3(latest_revnum, admobj->adm, target,
937 use_commit_times, recurse?svn_depth_infinity:svn_depth_files,
938 depth_is_sticky, allow_unver_obstructions,
939 py_wc_notify_func, (void *)notify_func,
940 py_cancel_func, (void *)cancel_func,
941 NULL, NULL, NULL, NULL,
942 diff3_cmd, NULL, &editor, &edit_baton,
945 if (allow_unver_obstructions) {
946 PyErr_SetString(PyExc_NotImplementedError,
947 "allow_unver_obstructions is not supported in svn < 1.5");
948 apr_pool_destroy(pool);
949 PyEval_RestoreThread(_save);
952 if (depth_is_sticky) {
953 PyErr_SetString(PyExc_NotImplementedError,
954 "depth_is_sticky is not supported in svn < 1.5");
955 apr_pool_destroy(pool);
956 PyEval_RestoreThread(_save);
959 err = svn_wc_get_update_editor2(latest_revnum, admobj->adm, target,
960 use_commit_times, recurse, py_wc_notify_func, (void *)notify_func,
961 py_cancel_func, (void *)cancel_func, diff3_cmd, &editor, &edit_baton,
964 if (!check_error(err)) {
965 apr_pool_destroy(pool);
966 PyEval_RestoreThread(_save);
970 return new_editor_object(editor, edit_baton, pool, &Editor_Type, NULL, NULL, NULL);
973 static bool py_dict_to_wcprop_changes(PyObject *dict, apr_pool_t *pool, apr_array_header_t **ret)
978 if (dict == Py_None) {
983 if (!PyDict_Check(dict)) {
984 PyErr_SetString(PyExc_TypeError, "Expected dictionary with property changes");
988 *ret = apr_array_make(pool, PyDict_Size(dict), sizeof(char *));
990 while (PyDict_Next(dict, &idx, &key, &val)) {
991 svn_prop_t *prop = apr_palloc(pool, sizeof(svn_prop_t));
992 prop->name = PyString_AsString(key);
993 if (val == Py_None) {
996 prop->value = svn_string_ncreate(PyString_AsString(val), PyString_Size(val), pool);
998 APR_ARRAY_PUSH(*ret, svn_prop_t *) = prop;
1004 static PyObject *adm_has_binary_prop(PyObject *self, PyObject *args)
1007 svn_boolean_t binary;
1008 AdmObject *admobj = (AdmObject *)self;
1009 apr_pool_t *temp_pool;
1011 if (!PyArg_ParseTuple(args, "s", &path))
1014 ADM_CHECK_CLOSED(admobj);
1016 temp_pool = Pool(NULL);
1017 if (temp_pool == NULL)
1020 RUN_SVN_WITH_POOL(temp_pool, svn_wc_has_binary_prop(&binary, path, admobj->adm, temp_pool));
1022 apr_pool_destroy(temp_pool);
1024 return PyBool_FromLong(binary);
1027 static PyObject *adm_process_committed(PyObject *self, PyObject *args, PyObject *kwargs)
1029 char *path, *rev_date = NULL, *rev_author = NULL;
1030 bool recurse, remove_lock = false;
1031 unsigned char *digest = NULL;
1032 svn_revnum_t new_revnum;
1033 PyObject *py_wcprop_changes = Py_None;
1034 apr_array_header_t *wcprop_changes = NULL;
1035 AdmObject *admobj = (AdmObject *)self;
1036 apr_pool_t *temp_pool;
1037 svn_boolean_t remove_changelist = FALSE;
1038 char *kwnames[] = { "path", "recurse", "new_revnum", "rev_date", "rev_author",
1039 "wcprop_changes", "remove_lock", "digest", "remove_changelist", NULL };
1041 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sblzz|Obzb", kwnames,
1042 &path, &recurse, &new_revnum, &rev_date,
1043 &rev_author, &py_wcprop_changes,
1044 &remove_lock, &digest, &remove_changelist))
1047 #if PY_VERSION_HEX < 0x02050000
1048 PyErr_Warn(PyExc_DeprecationWarning, "process_committed is deprecated. Use process_committed_queue instead.");
1050 PyErr_WarnEx(PyExc_DeprecationWarning, "process_committed is deprecated. Use process_committed_queue instead.", 2);
1054 ADM_CHECK_CLOSED(admobj);
1056 temp_pool = Pool(NULL);
1057 if (temp_pool == NULL)
1060 if (!py_dict_to_wcprop_changes(py_wcprop_changes, temp_pool, &wcprop_changes)) {
1061 apr_pool_destroy(temp_pool);
1065 #if ONLY_SINCE_SVN(1, 6)
1066 RUN_SVN_WITH_POOL(temp_pool, svn_wc_process_committed4(
1067 svn_path_canonicalize(path, temp_pool), admobj->adm, recurse, new_revnum,
1068 rev_date, rev_author, wcprop_changes,
1069 remove_lock, remove_changelist, digest, temp_pool));
1071 if (remove_changelist) {
1072 PyErr_SetString(PyExc_NotImplementedError, "remove_changelist only supported in svn < 1.6");
1073 apr_pool_destroy(temp_pool);
1076 RUN_SVN_WITH_POOL(temp_pool, svn_wc_process_committed3(svn_path_canonicalize(path, temp_pool), admobj->adm, recurse, new_revnum,
1077 rev_date, rev_author, wcprop_changes,
1078 remove_lock, digest, temp_pool));
1081 apr_pool_destroy(temp_pool);
1086 static PyObject *adm_close(PyObject *self)
1088 AdmObject *admobj = (AdmObject *)self;
1089 if (admobj->adm != NULL) {
1090 #if ONLY_SINCE_SVN(1, 6)
1091 apr_pool_t *temp_pool = Pool(NULL);
1092 Py_BEGIN_ALLOW_THREADS
1093 svn_wc_adm_close2(admobj->adm, temp_pool);
1094 apr_pool_destroy(temp_pool);
1096 Py_BEGIN_ALLOW_THREADS
1097 svn_wc_adm_close(admobj->adm);
1099 Py_END_ALLOW_THREADS
1106 static void adm_dealloc(PyObject *self)
1108 apr_pool_destroy(((AdmObject *)self)->pool);
1112 static PyObject *adm_repr(PyObject *self)
1114 AdmObject *admobj = (AdmObject *)self;
1116 if (admobj->adm == NULL) {
1117 return PyString_FromFormat("<wc.WorkingCopy (closed) at 0x%p>", admobj);
1119 return PyString_FromFormat("<wc.WorkingCopy at '%s'>",
1120 svn_wc_adm_access_path(admobj->adm));
1124 static PyObject *adm_remove_lock(PyObject *self, PyObject *args)
1127 AdmObject *admobj = (AdmObject *)self;
1128 apr_pool_t *temp_pool;
1130 if (!PyArg_ParseTuple(args, "s", &path))
1133 ADM_CHECK_CLOSED(admobj);
1135 temp_pool = Pool(NULL);
1136 if (temp_pool == NULL)
1139 RUN_SVN_WITH_POOL(temp_pool, svn_wc_remove_lock(path, admobj->adm, temp_pool))
1141 apr_pool_destroy(temp_pool);
1146 static PyObject *get_ancestry(PyObject *self, PyObject *args)
1151 apr_pool_t *temp_pool;
1152 AdmObject *admobj = (AdmObject *)self;
1154 if (!PyArg_ParseTuple(args, "s", &path))
1157 ADM_CHECK_CLOSED(admobj);
1159 temp_pool = Pool(NULL);
1160 if (temp_pool == NULL)
1163 RUN_SVN_WITH_POOL(temp_pool, svn_wc_get_ancestry(&url, &rev, path, admobj->adm, temp_pool));
1165 apr_pool_destroy(temp_pool);
1167 return Py_BuildValue("(si)", url, rev);
1170 static PyObject *maybe_set_repos_root(PyObject *self, PyObject *args)
1173 apr_pool_t *temp_pool;
1174 AdmObject *admobj = (AdmObject *)self;
1176 if (!PyArg_ParseTuple(args, "ss", &path, &repos))
1179 ADM_CHECK_CLOSED(admobj);
1181 temp_pool = Pool(NULL);
1182 if (temp_pool == NULL)
1185 RUN_SVN_WITH_POOL(temp_pool, svn_wc_maybe_set_repos_root(admobj->adm, path, repos, temp_pool));
1190 static PyObject *add_repos_file(PyObject *self, PyObject *args, PyObject *kwargs)
1192 char *kwnames[] = { "dst_path", "new_base_contents", "new_contents",
1193 "new_base_props", "new_props", "copyfrom_url", "copyfrom_rev",
1194 "cancel_func", "notify", NULL };
1195 AdmObject *admobj = (AdmObject *)self;
1196 apr_pool_t *temp_pool;
1197 char *dst_path, *copyfrom_url = NULL;
1198 svn_revnum_t copyfrom_rev = -1;
1199 PyObject *py_new_base_contents, *py_new_contents, *py_new_base_props,
1200 *py_new_props, *cancel_func = Py_None, *notify = Py_None;
1201 svn_stream_t *new_contents, *new_base_contents;
1202 apr_hash_t *new_props, *new_base_props;
1204 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOOOO|ziOO", kwnames,
1205 &dst_path, &py_new_base_contents, &py_new_contents, &py_new_base_props,
1206 &py_new_props, ©from_url, ©from_rev, &cancel_func, ¬ify))
1209 ADM_CHECK_CLOSED(admobj);
1211 temp_pool = Pool(NULL);
1212 if (temp_pool == NULL)
1215 new_base_props = prop_dict_to_hash(temp_pool, py_new_base_props);
1217 new_props = prop_dict_to_hash(temp_pool, py_new_props);
1219 new_base_contents = new_py_stream(temp_pool, py_new_base_contents);
1221 new_contents = new_py_stream(temp_pool, py_new_contents);
1223 #if ONLY_BEFORE_SVN(1, 6)
1224 if (cancel_func != Py_None) {
1225 PyErr_SetString(PyExc_NotImplementedError,
1226 "cancel not support for svn < 1.6");
1231 #if ONLY_SINCE_SVN(1, 6)
1232 RUN_SVN_WITH_POOL(temp_pool, svn_wc_add_repos_file3(dst_path, admobj->adm,
1237 copyfrom_url, copyfrom_rev,
1238 py_cancel_func, cancel_func,
1239 py_wc_notify_func, notify, temp_pool));
1241 PyErr_SetString(PyExc_NotImplementedError,
1242 "add_repos_file3 not supported on svn < 1.6");
1243 apr_pool_destroy(temp_pool);
1246 apr_pool_destroy(temp_pool);
1251 static PyObject *mark_missing_deleted(PyObject *self, PyObject *args)
1254 AdmObject *admobj = (AdmObject *)self;
1255 apr_pool_t *temp_pool;
1257 if (!PyArg_ParseTuple(args, "s", &path))
1260 ADM_CHECK_CLOSED(admobj);
1262 temp_pool = Pool(NULL);
1263 if (temp_pool == NULL)
1266 RUN_SVN_WITH_POOL(temp_pool, svn_wc_mark_missing_deleted(path, admobj->adm, temp_pool));
1268 apr_pool_destroy(temp_pool);
1273 static PyObject *remove_from_revision_control(PyObject *self, PyObject *args)
1276 svn_boolean_t destroy_wf = FALSE, instant_error = FALSE;
1277 AdmObject *admobj = (AdmObject *)self;
1278 PyObject *cancel_func = Py_None;
1279 apr_pool_t *temp_pool;
1281 if (!PyArg_ParseTuple(args, "s|bbO", &name, &destroy_wf, &instant_error, &cancel_func))
1284 ADM_CHECK_CLOSED(admobj);
1286 temp_pool = Pool(NULL);
1287 if (temp_pool == NULL)
1290 RUN_SVN_WITH_POOL(temp_pool,
1291 svn_wc_remove_from_revision_control(admobj->adm, name,
1292 destroy_wf, instant_error, py_cancel_func, cancel_func, temp_pool));
1294 apr_pool_destroy(temp_pool);
1299 #if ONLY_SINCE_SVN(1, 6)
1300 static svn_error_t *wc_validator3(void *baton, const char *uuid, const char *url, const char *root_url, apr_pool_t *pool)
1302 PyObject *py_validator = baton, *ret;
1304 if (py_validator == Py_None) {
1308 ret = PyObject_CallFunction(py_validator, "sss", uuid, url, root_url);
1310 return py_svn_error();
1320 static svn_error_t *wc_validator2(void *baton, const char *uuid, const char *url, svn_boolean_t root, apr_pool_t *pool)
1322 PyObject *py_validator = baton, *ret;
1324 if (py_validator == Py_None) {
1328 ret = PyObject_CallFunction(py_validator, "ssO", uuid, url, Py_None);
1330 return py_svn_error();
1340 static PyObject *relocate(PyObject *self, PyObject *args)
1342 char *path, *from, *to;
1343 AdmObject *admobj = (AdmObject *)self;
1344 apr_pool_t *temp_pool;
1345 svn_boolean_t recurse = TRUE;
1346 PyObject *py_validator = Py_None;
1348 if (!PyArg_ParseTuple(args, "sss|bO", &path, &from, &to, &recurse, &py_validator))
1351 ADM_CHECK_CLOSED(admobj);
1353 temp_pool = Pool(NULL);
1354 if (temp_pool == NULL)
1357 #if ONLY_SINCE_SVN(1, 6)
1358 RUN_SVN_WITH_POOL(temp_pool, svn_wc_relocate3(path, admobj->adm, from, to, recurse, wc_validator3, py_validator, temp_pool));
1360 RUN_SVN_WITH_POOL(temp_pool, svn_wc_relocate2(path, admobj->adm, from, to, recurse, wc_validator2, py_validator, temp_pool));
1363 apr_pool_destroy(temp_pool);
1368 static PyObject *crop_tree(PyObject *self, PyObject *args)
1372 PyObject *notify, *cancel;
1373 apr_pool_t *temp_pool;
1374 AdmObject *admobj = (AdmObject *)self;
1376 if (!PyArg_ParseTuple(args, "si|OO", &target, &depth, ¬ify, &cancel))
1379 ADM_CHECK_CLOSED(admobj);
1381 #if ONLY_SINCE_SVN(1, 6)
1382 temp_pool = Pool(NULL);
1383 if (temp_pool == NULL)
1386 RUN_SVN_WITH_POOL(temp_pool, svn_wc_crop_tree(admobj->adm,
1387 target, depth, py_wc_notify_func, notify,
1388 py_cancel_func, cancel, temp_pool));
1390 apr_pool_destroy(temp_pool);
1394 PyErr_SetString(PyExc_NotImplementedError,
1395 "crop_tree only available on subversion < 1.6");
1400 static PyObject *translated_stream(PyObject *self, PyObject *args)
1402 char *path, *versioned_file;
1404 svn_stream_t *stream;
1405 AdmObject *admobj = (AdmObject *)self;
1406 apr_pool_t *stream_pool;
1409 if (!PyArg_ParseTuple(args, "ssi", &path, &versioned_file, &flags))
1412 ADM_CHECK_CLOSED(admobj);
1414 #if ONLY_SINCE_SVN(1, 5)
1415 stream_pool = Pool(NULL);
1416 if (stream_pool == NULL)
1419 RUN_SVN_WITH_POOL(stream_pool,
1420 svn_wc_translated_stream(&stream, path, versioned_file, admobj->adm,
1421 flags, stream_pool));
1423 ret = PyObject_New(StreamObject, &Stream_Type);
1427 ret->pool = stream_pool;
1428 ret->closed = FALSE;
1429 ret->stream = stream;
1431 return (PyObject *)ret;
1433 PyErr_SetString(PyExc_NotImplementedError,
1434 "translated_stream() is only available on Subversion >= 1.5");
1439 static PyObject *adm_text_modified(PyObject *self, PyObject *args)
1442 svn_boolean_t force_comparison = FALSE;
1443 apr_pool_t *temp_pool;
1445 AdmObject *admobj = (AdmObject *)self;
1447 if (!PyArg_ParseTuple(args, "s|b", &path, &force_comparison))
1450 ADM_CHECK_CLOSED(admobj);
1452 temp_pool = Pool(NULL);
1453 if (temp_pool == NULL)
1456 RUN_SVN_WITH_POOL(temp_pool,
1457 svn_wc_text_modified_p(&ret, path, force_comparison, admobj->adm,
1460 apr_pool_destroy(temp_pool);
1462 return PyBool_FromLong(ret);
1465 static PyObject *adm_props_modified(PyObject *self, PyObject *args)
1468 apr_pool_t *temp_pool;
1470 AdmObject *admobj = (AdmObject *)self;
1472 if (!PyArg_ParseTuple(args, "s", &path))
1475 ADM_CHECK_CLOSED(admobj);
1477 temp_pool = Pool(NULL);
1478 if (temp_pool == NULL)
1481 RUN_SVN_WITH_POOL(temp_pool,
1482 svn_wc_props_modified_p(&ret, path, admobj->adm, temp_pool));
1484 apr_pool_destroy(temp_pool);
1486 return PyBool_FromLong(ret);
1489 static PyObject *adm_process_committed_queue(PyObject *self, PyObject *args)
1491 apr_pool_t *temp_pool;
1492 AdmObject *admobj = (AdmObject *)self;
1493 svn_revnum_t revnum;
1494 char *date, *author;
1495 CommittedQueueObject *py_queue;
1497 if (!PyArg_ParseTuple(args, "O!Iss", &CommittedQueue_Type, &py_queue, &revnum, &date, &author))
1500 ADM_CHECK_CLOSED(admobj);
1502 temp_pool = Pool(NULL);
1503 if (temp_pool == NULL)
1506 #if ONLY_SINCE_SVN(1, 5)
1507 RUN_SVN_WITH_POOL(temp_pool, svn_wc_process_committed_queue(py_queue->queue, admobj->adm, revnum, date, author, temp_pool));
1511 for (i = 0; i < py_queue->queue->queue->nelts; i++) {
1512 committed_queue_item_t *cqi = APR_ARRAY_IDX(py_queue->queue->queue, i,
1513 committed_queue_item_t *);
1515 RUN_SVN_WITH_POOL(temp_pool, svn_wc_process_committed3(cqi->path, admobj->adm,
1516 cqi->recurse, revnum, date, author, cqi->wcprop_changes,
1517 cqi->remove_lock, cqi->digest, temp_pool));
1521 apr_pool_destroy(temp_pool);
1526 static PyObject *get_actual_target(PyObject *self, PyObject *args)
1529 const char *anchor = NULL, *target = NULL;
1530 apr_pool_t *temp_pool;
1533 if (!PyArg_ParseTuple(args, "s", &path))
1536 temp_pool = Pool(NULL);
1537 if (temp_pool == NULL)
1540 RUN_SVN_WITH_POOL(temp_pool,
1541 svn_wc_get_actual_target(svn_path_canonicalize(path, temp_pool),
1542 &anchor, &target, temp_pool));
1544 ret = Py_BuildValue("(ss)", anchor, target);
1546 apr_pool_destroy(temp_pool);
1551 static PyObject *is_wc_root(PyObject *self, PyObject *args)
1554 svn_boolean_t wc_root;
1555 apr_pool_t *temp_pool;
1556 AdmObject *admobj = (AdmObject *)self;
1558 if (!PyArg_ParseTuple(args, "s", &path))
1561 ADM_CHECK_CLOSED(admobj);
1563 temp_pool = Pool(NULL);
1564 if (temp_pool == NULL)
1567 RUN_SVN_WITH_POOL(temp_pool,
1568 svn_wc_is_wc_root(&wc_root, path, admobj->adm, temp_pool));
1570 apr_pool_destroy(temp_pool);
1572 return PyBool_FromLong(wc_root);
1575 static PyObject *transmit_text_deltas(PyObject *self, PyObject *args)
1578 const char *tempfile;
1579 svn_boolean_t fulltext;
1580 PyObject *editor_obj, *py_digest;
1581 unsigned char digest[APR_MD5_DIGESTSIZE];
1582 apr_pool_t *temp_pool;
1583 AdmObject *admobj = (AdmObject *)self;
1586 if (!PyArg_ParseTuple(args, "sbO", &path, &fulltext, &editor_obj))
1589 ADM_CHECK_CLOSED(admobj);
1591 temp_pool = Pool(NULL);
1592 if (temp_pool == NULL)
1595 Py_INCREF(editor_obj);
1597 RUN_SVN_WITH_POOL(temp_pool,
1598 svn_wc_transmit_text_deltas2(&tempfile, digest,
1599 svn_path_canonicalize(path, temp_pool), admobj->adm, fulltext,
1600 &py_editor, editor_obj, temp_pool));
1602 py_digest = PyString_FromStringAndSize((char *)digest, APR_MD5_DIGESTSIZE);
1603 if (py_digest == NULL) {
1604 apr_pool_destroy(temp_pool);
1608 ret = Py_BuildValue("sN", tempfile, py_digest);
1610 apr_pool_destroy(temp_pool);
1614 apr_pool_destroy(temp_pool);
1619 static PyObject *transmit_prop_deltas(PyObject *self, PyObject *args)
1622 PyObject *editor_obj;
1623 apr_pool_t *temp_pool;
1624 AdmObject *admobj = (AdmObject *)self;
1625 EntryObject *py_entry;
1627 if (!PyArg_ParseTuple(args, "sO!O", &path, &Entry_Type, &py_entry, &editor_obj))
1630 ADM_CHECK_CLOSED(admobj);
1632 temp_pool = Pool(NULL);
1633 if (temp_pool == NULL)
1636 Py_INCREF(editor_obj);
1638 RUN_SVN_WITH_POOL(temp_pool,
1639 svn_wc_transmit_prop_deltas(svn_path_canonicalize(path, temp_pool),
1640 admobj->adm, &(py_entry->entry), &py_editor, editor_obj, NULL, temp_pool));
1642 apr_pool_destroy(temp_pool);
1647 static PyObject *retrieve(PyObject *self, PyObject *args)
1650 svn_wc_adm_access_t *result;
1651 AdmObject *admobj = (AdmObject *)self, *ret;
1654 if (!PyArg_ParseTuple(args, "s", &path))
1657 ADM_CHECK_CLOSED(admobj);
1663 RUN_SVN_WITH_POOL(pool, svn_wc_adm_retrieve(&result, admobj->adm,
1664 svn_path_canonicalize(path, pool), pool));
1666 ret = PyObject_New(AdmObject, &Adm_Type);
1673 return (PyObject *)ret;
1676 static PyObject *probe_retrieve(PyObject *self, PyObject *args)
1679 svn_wc_adm_access_t *result;
1680 AdmObject *admobj = (AdmObject *)self, *ret;
1683 if (!PyArg_ParseTuple(args, "s", &path))
1686 ADM_CHECK_CLOSED(admobj);
1692 RUN_SVN_WITH_POOL(pool, svn_wc_adm_probe_retrieve(&result, admobj->adm,
1693 svn_path_canonicalize(path, pool), pool));
1695 ret = PyObject_New(AdmObject, &Adm_Type);
1702 return (PyObject *)ret;
1705 static PyObject *probe_try(PyObject *self, PyObject *args)
1708 svn_wc_adm_access_t *result = NULL;
1709 AdmObject *admobj = (AdmObject *)self, *ret;
1711 PyObject *cancelfunc = Py_None;
1712 int levels_to_lock = -1;
1713 svn_boolean_t writelock = FALSE;
1715 if (!PyArg_ParseTuple(args, "s|biO", &path, &writelock, &levels_to_lock, &cancelfunc))
1718 ADM_CHECK_CLOSED(admobj);
1724 RUN_SVN_WITH_POOL(pool, svn_wc_adm_probe_try3(&result, admobj->adm,
1725 svn_path_canonicalize(path, pool), writelock, levels_to_lock,
1726 py_cancel_func, cancelfunc, pool));
1728 if (result == NULL) {
1729 apr_pool_destroy(pool);
1733 ret = PyObject_New(AdmObject, &Adm_Type);
1740 return (PyObject *)ret;
1743 static PyObject *resolved_conflict(PyObject *self, PyObject *args)
1745 AdmObject *admobj = (AdmObject *)self;
1746 apr_pool_t *temp_pool;
1747 svn_boolean_t resolve_props, resolve_tree, resolve_text;
1749 svn_wc_conflict_choice_t conflict_choice;
1750 PyObject *notify_func = Py_None, *cancel_func = Py_None;
1753 if (!PyArg_ParseTuple(args, "sbbbii|OO", &path, &resolve_text,
1754 &resolve_props, &resolve_tree, &depth,
1755 &conflict_choice, ¬ify_func, &cancel_func))
1758 ADM_CHECK_CLOSED(admobj);
1760 temp_pool = Pool(NULL);
1761 if (temp_pool == NULL)
1764 #if ONLY_SINCE_SVN(1, 6)
1765 RUN_SVN_WITH_POOL(temp_pool,
1766 svn_wc_resolved_conflict4(path, admobj->adm, resolve_text,
1767 resolve_props, resolve_tree, depth,
1768 conflict_choice, py_wc_notify_func,
1769 (void *)notify_func, py_cancel_func,
1770 cancel_func, temp_pool));
1771 #elif ONLY_SINCE_SVN(1, 5)
1773 PyErr_SetString(PyExc_NotImplementedError,
1774 "resolve_tree not supported with svn < 1.6");
1776 RUN_SVN_WITH_POOL(temp_pool,
1777 svn_wc_resolved_conflict3(path, admobj->adm, resolve_text,
1778 resolve_props, depth,
1779 conflict_choice, py_wc_notify_func,
1780 (void *)notify_func, py_cancel_func,
1781 cancel_func, temp_pool));
1785 PyErr_SetString(PyExc_NotImplementedError,
1786 "resolve_tree not supported with svn < 1.6");
1787 } else if (depth != svn_depth_infinity && depth != svn_depth_empty) {
1788 PyErr_SetString(PyExc_NotImplementedError,
1789 "only infinity and empty values for depth are supported");
1791 RUN_SVN_WITH_POOL(temp_pool,
1792 svn_wc_resolved_conflict3(path, admobj->adm, resolve_text,
1794 (depth == svn_depth_infinity),
1795 conflict_choice, py_wc_notify_func,
1796 (void *)notify_func, py_cancel_func,
1797 cancel_func, temp_pool));
1801 apr_pool_destroy(temp_pool);
1806 static PyObject *conflicted(PyObject *self, PyObject *args)
1809 apr_pool_t *temp_pool;
1811 AdmObject *admobj = (AdmObject *)self;
1812 svn_boolean_t text_conflicted, prop_conflicted, tree_conflicted;
1814 if (!PyArg_ParseTuple(args, "s", &path))
1817 ADM_CHECK_CLOSED(admobj);
1819 temp_pool = Pool(NULL);
1820 if (temp_pool == NULL)
1823 #if ONLY_SINCE_SVN(1, 6)
1824 RUN_SVN_WITH_POOL(temp_pool, svn_wc_conflicted_p2(&text_conflicted,
1825 &prop_conflicted, &tree_conflicted, path, admobj->adm, temp_pool));
1827 ret = Py_BuildValue("(bbb)", text_conflicted, prop_conflicted, tree_conflicted);
1829 RUN_SVN_WITH_POOL(temp_pool, svn_wc_conflicted_p(&text_conflicted,
1830 &prop_conflicted, path, admobj->adm, temp_pool));
1832 ret = Py_BuildValue("(bbO)", text_conflicted, prop_conflicted, Py_None);
1835 apr_pool_destroy(temp_pool);
1840 static PyMethodDef adm_methods[] = {
1841 { "prop_set", adm_prop_set, METH_VARARGS, "S.prop_set(name, value, path, skip_checks=False)" },
1842 { "access_path", (PyCFunction)adm_access_path, METH_NOARGS,
1843 "S.access_path() -> path\n"
1844 "Returns the base path for this working copy handle." },
1845 { "prop_get", adm_prop_get, METH_VARARGS, "S.prop_get(name, path) -> value" },
1846 { "entries_read", adm_entries_read, METH_VARARGS, "S.entries_read(include_hidden=False) -> dict" },
1847 { "walk_entries", adm_walk_entries, METH_VARARGS,
1848 "S.walk_entries(path, callback, show_hidden=False, cancel_func=None)\n"
1849 "callback should be a function that takes a path and a wc entry" },
1850 { "locked", (PyCFunction)adm_locked, METH_NOARGS,
1851 "S.locked() -> bool" },
1852 { "get_prop_diffs", adm_get_prop_diffs, METH_VARARGS,
1853 "S.get_prop_diffs(path) -> (propchanges, originalprops)" },
1854 { "add", (PyCFunction)adm_add, METH_VARARGS|METH_KEYWORDS, "S.add(path, copyfrom_url=None, copyfrom_rev=-1, cancel_func=None, notify_func=None)" },
1855 { "copy", adm_copy, METH_VARARGS, "S.copy(src_path, dest_path, cancel_func=None, notify_func=None)" },
1856 { "delete", (PyCFunction)adm_delete, METH_VARARGS|METH_KEYWORDS, "S.delete(path, cancel_func=None, notify_func=None, keep_local=False)" },
1857 { "crawl_revisions", (PyCFunction)adm_crawl_revisions, METH_VARARGS|METH_KEYWORDS,
1858 "S.crawl_revisions(path, reporter, restore_files=True, recurse=True, use_commit_times=True, notify_func=None) -> None" },
1859 { "get_update_editor", adm_get_update_editor, METH_VARARGS, NULL },
1860 { "close", (PyCFunction)adm_close, METH_NOARGS,
1862 { "entry", (PyCFunction)adm_entry, METH_VARARGS,
1863 "s.entry(path, show_hidden=False) -> entry" },
1864 { "process_committed", (PyCFunction)adm_process_committed, METH_VARARGS|METH_KEYWORDS, "S.process_committed(path, recurse, new_revnum, rev_date, rev_author, wcprop_changes=None, remove_lock=False, digest=None)" },
1865 { "process_committed_queue", (PyCFunction)adm_process_committed_queue, METH_VARARGS, "S.process_committed_queue(queue, new_revnum, rev_date, rev_author)" },
1866 { "remove_lock", (PyCFunction)adm_remove_lock, METH_VARARGS, "S.remove_lock(path)" },
1867 { "has_binary_prop", (PyCFunction)adm_has_binary_prop, METH_VARARGS, "S.has_binary_prop(path) -> bool" },
1868 { "text_modified", (PyCFunction)adm_text_modified, METH_VARARGS, "S.text_modified(filename, force_comparison=False) -> bool" },
1869 { "props_modified", (PyCFunction)adm_props_modified, METH_VARARGS, "S.props_modified(filename) -> bool" },
1870 { "get_ancestry", (PyCFunction)get_ancestry, METH_VARARGS,
1871 "S.get_ancestry(path) -> (url, rev)" },
1872 { "maybe_set_repos_root", (PyCFunction)maybe_set_repos_root, METH_VARARGS, "S.maybe_set_repos_root(path, repos)" },
1873 { "add_repos_file", (PyCFunction)add_repos_file, METH_KEYWORDS,
1874 "S.add_repos_file(dst_path, new_base_contents, new_contents, new_base_props, new_props, copyfrom_url=None, copyfrom_rev=-1, cancel_func=None, notify_func=None)" },
1875 { "mark_missing_deleted", (PyCFunction)mark_missing_deleted, METH_VARARGS,
1876 "S.mark_missing_deleted(path)" },
1877 { "remove_from_revision_control", (PyCFunction)remove_from_revision_control, METH_VARARGS,
1878 "S.remove_from_revision_control(name, destroy_wf=False, instant_error=False, cancel_func=None)" },
1879 { "relocate", (PyCFunction)relocate, METH_VARARGS,
1880 "S.relocate(path, from, to, recurse=TRUE, validator=None)" },
1881 { "crop_tree", (PyCFunction)crop_tree, METH_VARARGS,
1882 "S.crop_tree(target, depth, notify_func=None, cancel=None)" },
1883 { "translated_stream", (PyCFunction)translated_stream, METH_VARARGS,
1884 "S.translated_stream(path, versioned_file, flags) -> stream" },
1885 { "is_wc_root", (PyCFunction)is_wc_root, METH_VARARGS,
1886 "S.is_wc_root(path) -> wc_root" },
1887 { "transmit_text_deltas", (PyCFunction)transmit_text_deltas, METH_VARARGS,
1888 "S.transmit_text_deltas(fulltext, editor) -> (tempfile, digest)" },
1889 { "transmit_prop_deltas", (PyCFunction)transmit_prop_deltas, METH_VARARGS,
1890 "S.transmit_prop_deltas(path, entry, editor)" },
1891 { "probe_retrieve", (PyCFunction)probe_retrieve, METH_VARARGS,
1892 "S.probe_retrieve(path) -> WorkingCopy" },
1893 { "retrieve", (PyCFunction)retrieve, METH_VARARGS,
1894 "S.retrieve(path) -> WorkingCopy" },
1895 { "probe_try", (PyCFunction)probe_try, METH_VARARGS,
1896 "S.probe_try(path, write_lock=False, levels_to_lock=-1)" },
1897 { "conflicted", (PyCFunction)conflicted, METH_VARARGS,
1898 "S.conflicted(path) -> (text_conflicted, prop_conflicted, tree_conflicted)" },
1899 { "resolved_conflict", (PyCFunction)resolved_conflict, METH_VARARGS,
1900 "S.resolved_conflict(path, resolve_text, resolve_props, resolve_tree, depth, conflict_choice, notify_func=None, cancel=None)" },
1904 static PyTypeObject Adm_Type = {
1905 PyObject_HEAD_INIT(NULL) 0,
1906 "wc.WorkingCopy", /* const char *tp_name; For printing, in format "<module>.<name>" */
1908 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
1910 /* Methods to implement standard operations */
1912 adm_dealloc, /* destructor tp_dealloc; */
1913 NULL, /* printfunc tp_print; */
1914 NULL, /* getattrfunc tp_getattr; */
1915 NULL, /* setattrfunc tp_setattr; */
1916 NULL, /* cmpfunc tp_compare; */
1917 adm_repr, /* reprfunc tp_repr; */
1919 /* Method suites for standard classes */
1921 NULL, /* PyNumberMethods *tp_as_number; */
1922 NULL, /* PySequenceMethods *tp_as_sequence; */
1923 NULL, /* PyMappingMethods *tp_as_mapping; */
1925 /* More standard operations (here for binary compatibility) */
1927 NULL, /* hashfunc tp_hash; */
1928 NULL, /* ternaryfunc tp_call; */
1929 adm_repr, /* reprfunc tp_repr; */
1930 NULL, /* getattrofunc tp_getattro; */
1931 NULL, /* setattrofunc tp_setattro; */
1933 /* Functions to access object as input/output buffer */
1934 NULL, /* PyBufferProcs *tp_as_buffer; */
1936 /* Flags to define presence of optional/expanded features */
1937 0, /* long tp_flags; */
1939 "Local working copy", /* const char *tp_doc; Documentation string */
1941 /* Assigned meaning in release 2.0 */
1942 /* call function for all accessible objects */
1943 NULL, /* traverseproc tp_traverse; */
1945 /* delete references to contained objects */
1946 NULL, /* inquiry tp_clear; */
1948 /* Assigned meaning in release 2.1 */
1949 /* rich comparisons */
1950 NULL, /* richcmpfunc tp_richcompare; */
1952 /* weak reference enabler */
1953 0, /* Py_ssize_t tp_weaklistoffset; */
1955 /* Added in release 2.2 */
1957 NULL, /* getiterfunc tp_iter; */
1958 NULL, /* iternextfunc tp_iternext; */
1960 /* Attribute descriptor and subclassing stuff */
1961 adm_methods, /* struct PyMethodDef *tp_methods; */
1962 NULL, /* struct PyMemberDef *tp_members; */
1963 NULL, /* struct PyGetSetDef *tp_getset; */
1964 NULL, /* struct _typeobject *tp_base; */
1965 NULL, /* PyObject *tp_dict; */
1966 NULL, /* descrgetfunc tp_descr_get; */
1967 NULL, /* descrsetfunc tp_descr_set; */
1968 0, /* Py_ssize_t tp_dictoffset; */
1969 NULL, /* initproc tp_init; */
1970 NULL, /* allocfunc tp_alloc; */
1971 adm_init, /* newfunc tp_new; */
1974 static void committed_queue_dealloc(PyObject *self)
1976 apr_pool_destroy(((CommittedQueueObject *)self)->pool);
1980 static PyObject *committed_queue_repr(PyObject *self)
1982 CommittedQueueObject *cqobj = (CommittedQueueObject *)self;
1984 return PyString_FromFormat("<wc.CommittedQueue at 0x%p>", cqobj->queue);
1987 static PyObject *committed_queue_init(PyTypeObject *self, PyObject *args, PyObject *kwargs)
1989 CommittedQueueObject *ret;
1990 char *kwnames[] = { NULL };
1992 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwnames))
1995 ret = PyObject_New(CommittedQueueObject, &CommittedQueue_Type);
1999 ret->pool = Pool(NULL);
2000 if (ret->pool == NULL)
2002 ret->queue = svn_wc_committed_queue_create(ret->pool);
2003 if (ret->queue == NULL) {
2009 return (PyObject *)ret;
2012 static PyObject *committed_queue_queue(CommittedQueueObject *self, PyObject *args)
2016 PyObject *py_wcprop_changes = Py_None;
2017 svn_boolean_t remove_lock = FALSE, remove_changelist = FALSE;
2018 char *digest = NULL;
2019 svn_boolean_t recurse = FALSE;
2020 apr_pool_t *temp_pool;
2021 apr_array_header_t *wcprop_changes;
2023 if (!PyArg_ParseTuple(args, "sO!|bObbz", &path, &Adm_Type, &admobj, &recurse, &py_wcprop_changes, &remove_lock, &remove_changelist, &digest))
2026 temp_pool = Pool(NULL);
2027 if (temp_pool == NULL)
2030 if (!py_dict_to_wcprop_changes(py_wcprop_changes, self->pool, &wcprop_changes)) {
2031 apr_pool_destroy(temp_pool);
2035 path = apr_pstrdup(self->pool, path);
2041 if (digest != NULL) {
2042 digest = apr_pstrdup(self->pool, digest);
2043 if (digest == NULL) {
2049 RUN_SVN_WITH_POOL(temp_pool,
2050 svn_wc_queue_committed(&self->queue, path, admobj->adm, recurse,
2051 wcprop_changes, remove_lock, remove_changelist,
2052 (unsigned char *)digest, temp_pool));
2054 apr_pool_destroy(temp_pool);
2059 static PyMethodDef committed_queue_methods[] = {
2060 { "queue", (PyCFunction)committed_queue_queue, METH_VARARGS,
2061 "S.queue(path, adm, recurse, wcprop_changes, remove_lock, remove_changelist, digest)" },
2065 static PyTypeObject CommittedQueue_Type = {
2066 PyObject_HEAD_INIT(NULL) 0,
2067 "wc.CommittedQueue", /* const char *tp_name; For printing, in format "<module>.<name>" */
2068 sizeof(CommittedQueueObject),
2069 0,/* Py_ssize_t tp_basicsize, tp_itemsize; For allocation */
2071 /* Methods to implement standard operations */
2073 committed_queue_dealloc, /* destructor tp_dealloc; */
2074 NULL, /* printfunc tp_print; */
2075 NULL, /* getattrfunc tp_getattr; */
2076 NULL, /* setattrfunc tp_setattr; */
2077 NULL, /* cmpfunc tp_compare; */
2078 committed_queue_repr, /* reprfunc tp_repr; */
2080 /* Method suites for standard classes */
2082 NULL, /* PyNumberMethods *tp_as_number; */
2083 NULL, /* PySequenceMethods *tp_as_sequence; */
2084 NULL, /* PyMappingMethods *tp_as_mapping; */
2086 /* More standard operations (here for binary compatibility) */
2088 NULL, /* hashfunc tp_hash; */
2089 NULL, /* ternaryfunc tp_call; */
2090 NULL, /* reprfunc tp_str; */
2091 NULL, /* getattrofunc tp_getattro; */
2092 NULL, /* setattrofunc tp_setattro; */
2094 /* Functions to access object as input/output buffer */
2095 NULL, /* PyBufferProcs *tp_as_buffer; */
2097 /* Flags to define presence of optional/expanded features */
2098 0, /* long tp_flags; */
2100 "Committed queue", /* const char *tp_doc; Documentation string */
2102 /* Assigned meaning in release 2.0 */
2103 /* call function for all accessible objects */
2104 NULL, /* traverseproc tp_traverse; */
2106 /* delete references to contained objects */
2107 NULL, /* inquiry tp_clear; */
2109 /* Assigned meaning in release 2.1 */
2110 /* rich comparisons */
2111 NULL, /* richcmpfunc tp_richcompare; */
2113 /* weak reference enabler */
2114 0, /* Py_ssize_t tp_weaklistoffset; */
2116 /* Added in release 2.2 */
2118 NULL, /* getiterfunc tp_iter; */
2119 NULL, /* iternextfunc tp_iternext; */
2121 /* Attribute descriptor and subclassing stuff */
2122 committed_queue_methods, /* struct PyMethodDef *tp_methods; */
2123 NULL, /* struct PyMemberDef *tp_members; */
2124 NULL, /* struct PyGetSetDef *tp_getset; */
2125 NULL, /* struct _typeobject *tp_base; */
2126 NULL, /* PyObject *tp_dict; */
2127 NULL, /* descrgetfunc tp_descr_get; */
2128 NULL, /* descrsetfunc tp_descr_set; */
2129 0, /* Py_ssize_t tp_dictoffset; */
2130 NULL, /* initproc tp_init; */
2131 NULL, /* allocfunc tp_alloc; */
2132 committed_queue_init, /* newfunc tp_new; */
2136 * Determine the revision status of a specified working copy.
2138 * :return: Tuple with minimum and maximum revnums found, whether the
2139 * working copy was switched and whether it was modified.
2141 static PyObject *revision_status(PyObject *self, PyObject *args, PyObject *kwargs)
2143 char *kwnames[] = { "wc_path", "trail_url", "committed", "cancel_func", NULL };
2144 char *wc_path, *trail_url=NULL;
2145 bool committed=false;
2146 PyObject *cancel_func=Py_None, *ret;
2147 svn_wc_revision_status_t *revstatus;
2148 apr_pool_t *temp_pool;
2150 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zbO", kwnames, &wc_path,
2151 &trail_url, &committed, &cancel_func))
2154 temp_pool = Pool(NULL);
2155 if (temp_pool == NULL)
2157 RUN_SVN_WITH_POOL(temp_pool,
2158 svn_wc_revision_status(
2160 svn_path_canonicalize(wc_path, temp_pool),
2162 committed, py_cancel_func, cancel_func, temp_pool));
2163 ret = Py_BuildValue("(llbb)", revstatus->min_rev, revstatus->max_rev,
2164 revstatus->switched, revstatus->modified);
2165 apr_pool_destroy(temp_pool);
2169 static PyObject *is_normal_prop(PyObject *self, PyObject *args)
2173 if (!PyArg_ParseTuple(args, "s", &name))
2176 return PyBool_FromLong(svn_wc_is_normal_prop(name));
2179 static PyObject *is_adm_dir(PyObject *self, PyObject *args)
2185 if (!PyArg_ParseTuple(args, "s", &name))
2192 ret = svn_wc_is_adm_dir(name, pool);
2194 apr_pool_destroy(pool);
2196 return PyBool_FromLong(ret);
2199 static PyObject *is_wc_prop(PyObject *self, PyObject *args)
2203 if (!PyArg_ParseTuple(args, "s", &name))
2206 return PyBool_FromLong(svn_wc_is_wc_prop(name));
2209 static PyObject *is_entry_prop(PyObject *self, PyObject *args)
2213 if (!PyArg_ParseTuple(args, "s", &name))
2216 return PyBool_FromLong(svn_wc_is_entry_prop(name));
2219 static PyObject *get_adm_dir(PyObject *self)
2227 dir = svn_wc_get_adm_dir(pool);
2228 ret = PyString_FromString(dir);
2229 apr_pool_destroy(pool);
2233 static PyObject *set_adm_dir(PyObject *self, PyObject *args)
2235 apr_pool_t *temp_pool;
2238 if (!PyArg_ParseTuple(args, "s", &name))
2241 temp_pool = Pool(NULL);
2242 if (temp_pool == NULL)
2244 RUN_SVN_WITH_POOL(temp_pool, svn_wc_set_adm_dir(name, temp_pool));
2245 apr_pool_destroy(temp_pool);
2249 static PyObject *get_pristine_copy_path(PyObject *self, PyObject *args)
2252 const char *pristine_path;
2256 if (!PyArg_ParseTuple(args, "s", &path))
2262 #if PY_VERSION_HEX < 0x02050000
2263 PyErr_Warn(PyExc_DeprecationWarning, "get_pristine_copy_path is deprecated. Use get_pristine_contents instead.");
2265 PyErr_WarnEx(PyExc_DeprecationWarning, "get_pristine_copy_path is deprecated. Use get_pristine_contents instead.", 2);
2267 RUN_SVN_WITH_POOL(pool,
2268 svn_wc_get_pristine_copy_path(svn_path_canonicalize(path, pool),
2269 &pristine_path, pool));
2270 ret = PyString_FromString(pristine_path);
2271 apr_pool_destroy(pool);
2275 static PyObject *get_pristine_contents(PyObject *self, PyObject *args)
2278 apr_pool_t *temp_pool;
2279 #if ONLY_SINCE_SVN(1, 6)
2280 apr_pool_t *stream_pool;
2282 svn_stream_t *stream;
2285 const char *pristine_path;
2288 if (!PyArg_ParseTuple(args, "s", &path))
2291 #if ONLY_SINCE_SVN(1, 6)
2292 stream_pool = Pool(NULL);
2293 if (stream_pool == NULL)
2296 temp_pool = Pool(stream_pool);
2297 if (temp_pool == NULL) {
2298 apr_pool_destroy(stream_pool);
2302 RUN_SVN_WITH_POOL(stream_pool, svn_wc_get_pristine_contents(&stream, svn_path_canonicalize(path, temp_pool), stream_pool, temp_pool));
2303 apr_pool_destroy(temp_pool);
2305 if (stream == NULL) {
2306 apr_pool_destroy(stream_pool);
2310 ret = PyObject_New(StreamObject, &Stream_Type);
2314 ret->pool = stream_pool;
2315 ret->closed = FALSE;
2316 ret->stream = stream;
2318 return (PyObject *)ret;
2320 temp_pool = Pool(NULL);
2321 if (temp_pool == NULL)
2323 RUN_SVN_WITH_POOL(temp_pool, svn_wc_get_pristine_copy_path(svn_path_canonicalize(path, temp_pool), &pristine_path, temp_pool));
2324 ret = PyFile_FromString((char *)pristine_path, "rb");
2325 apr_pool_destroy(temp_pool);
2330 static PyObject *ensure_adm(PyObject *self, PyObject *args, PyObject *kwargs)
2332 char *path, *uuid, *url;
2334 svn_revnum_t rev=-1;
2336 char *kwnames[] = { "path", "uuid", "url", "repos", "rev", "depth", NULL };
2337 svn_depth_t depth = svn_depth_infinity;
2339 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|sli", kwnames,
2340 &path, &uuid, &url, &repos, &rev, &depth))
2346 #if ONLY_SINCE_SVN(1, 5)
2347 RUN_SVN_WITH_POOL(pool,
2348 svn_wc_ensure_adm3(svn_path_canonicalize(path, pool),
2349 uuid, url, repos, rev, depth, pool));
2351 if (depth != svn_depth_infinity) {
2352 PyErr_SetString(PyExc_NotImplementedError,
2353 "depth != infinity not supported with svn < 1.5");
2354 apr_pool_destroy(pool);
2357 RUN_SVN_WITH_POOL(pool,
2358 svn_wc_ensure_adm2(svn_path_canonicalize(path, pool),
2359 uuid, url, repos, rev, pool));
2361 apr_pool_destroy(pool);
2365 static PyObject *check_wc(PyObject *self, PyObject *args)
2371 if (!PyArg_ParseTuple(args, "s", &path))
2377 RUN_SVN_WITH_POOL(pool, svn_wc_check_wc(svn_path_canonicalize(path, pool), &wc_format, pool));
2378 apr_pool_destroy(pool);
2379 return PyLong_FromLong(wc_format);
2382 static PyObject *cleanup_wc(PyObject *self, PyObject *args, PyObject *kwargs)
2384 PyObject *cancel_func = Py_None;
2386 char *diff3_cmd = NULL;
2387 char *kwnames[] = { "path", "diff3_cmd", "cancel_func", NULL };
2388 apr_pool_t *temp_pool;
2390 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zO", kwnames,
2391 &path, &diff3_cmd, &cancel_func))
2394 temp_pool = Pool(NULL);
2395 if (temp_pool == NULL)
2397 RUN_SVN_WITH_POOL(temp_pool,
2398 svn_wc_cleanup2(path, diff3_cmd, py_cancel_func, cancel_func,
2400 apr_pool_destroy(temp_pool);
2405 static PyObject *match_ignore_list(PyObject *self, PyObject *args)
2407 #if ONLY_SINCE_SVN(1, 5)
2410 apr_array_header_t *list;
2411 apr_pool_t *temp_pool;
2414 if (!PyArg_ParseTuple(args, "sO", &str, &py_list))
2417 temp_pool = Pool(NULL);
2419 if (!string_list_to_apr_array(temp_pool, py_list, &list)) {
2420 apr_pool_destroy(temp_pool);
2424 ret = svn_wc_match_ignore_list(str, list, temp_pool);
2426 apr_pool_destroy(temp_pool);
2428 return PyBool_FromLong(ret);
2430 PyErr_SetNone(PyExc_NotImplementedError);
2435 static PyMethodDef wc_methods[] = {
2436 { "check_wc", check_wc, METH_VARARGS, "check_wc(path) -> version\n"
2437 "Check whether path contains a Subversion working copy\n"
2438 "return the workdir version"},
2439 { "cleanup", (PyCFunction)cleanup_wc, METH_VARARGS|METH_KEYWORDS, "cleanup(path, diff3_cmd=None, cancel_func=None)\n" },
2440 { "ensure_adm", (PyCFunction)ensure_adm, METH_KEYWORDS|METH_VARARGS,
2441 "ensure_adm(path, uuid, url, repos=None, rev=None)" },
2442 { "get_adm_dir", (PyCFunction)get_adm_dir, METH_NOARGS,
2443 "get_adm_dir() -> name" },
2444 { "set_adm_dir", (PyCFunction)set_adm_dir, METH_VARARGS,
2445 "set_adm_dir(name)" },
2446 { "get_pristine_copy_path", get_pristine_copy_path, METH_VARARGS,
2447 "get_pristine_copy_path(path) -> path" },
2448 { "get_pristine_contents", get_pristine_contents, METH_VARARGS,
2449 "get_pristine_contents(path) -> stream" },
2450 { "is_adm_dir", is_adm_dir, METH_VARARGS,
2451 "is_adm_dir(name) -> bool" },
2452 { "is_normal_prop", is_normal_prop, METH_VARARGS,
2453 "is_normal_prop(name) -> bool" },
2454 { "is_entry_prop", is_entry_prop, METH_VARARGS,
2455 "is_entry_prop(name) -> bool" },
2456 { "is_wc_prop", is_wc_prop, METH_VARARGS,
2457 "is_wc_prop(name) -> bool" },
2458 { "revision_status", (PyCFunction)revision_status, METH_KEYWORDS|METH_VARARGS, "revision_status(wc_path, trail_url=None, committed=False, cancel_func=None) -> (min_rev, max_rev, switched, modified)" },
2459 { "version", (PyCFunction)version, METH_NOARGS,
2460 "version() -> (major, minor, patch, tag)\n\n"
2461 "Version of libsvn_wc currently used."
2463 { "api_version", (PyCFunction)api_version, METH_NOARGS,
2464 "api_version() -> (major, minor, patch, tag)\n\n"
2465 "Version of libsvn_wc Subvertpy was compiled against."
2467 { "match_ignore_list", (PyCFunction)match_ignore_list, METH_VARARGS,
2468 "match_ignore_list(str, patterns) -> bool" },
2469 { "get_actual_target", (PyCFunction)get_actual_target, METH_VARARGS,
2470 "get_actual_target(path) -> (anchor, target)" },
2478 if (PyType_Ready(&Entry_Type) < 0)
2481 if (PyType_Ready(&Adm_Type) < 0)
2484 if (PyType_Ready(&Editor_Type) < 0)
2487 if (PyType_Ready(&FileEditor_Type) < 0)
2490 if (PyType_Ready(&DirectoryEditor_Type) < 0)
2493 if (PyType_Ready(&TxDeltaWindowHandler_Type) < 0)
2496 if (PyType_Ready(&Stream_Type) < 0)
2499 if (PyType_Ready(&CommittedQueue_Type) < 0)
2506 mod = Py_InitModule3("wc", wc_methods, "Working Copies");
2510 PyModule_AddIntConstant(mod, "SCHEDULE_NORMAL", 0);
2511 PyModule_AddIntConstant(mod, "SCHEDULE_ADD", 1);
2512 PyModule_AddIntConstant(mod, "SCHEDULE_DELETE", 2);
2513 PyModule_AddIntConstant(mod, "SCHEDULE_REPLACE", 3);
2515 #if ONLY_SINCE_SVN(1, 5)
2516 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_POSTPONE",
2517 svn_wc_conflict_choose_postpone);
2518 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_BASE",
2519 svn_wc_conflict_choose_base);
2520 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_THEIRS_FULL",
2521 svn_wc_conflict_choose_theirs_full);
2522 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_MINE_FULL",
2523 svn_wc_conflict_choose_mine_full);
2524 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_THEIRS_CONFLICT",
2525 svn_wc_conflict_choose_theirs_conflict);
2526 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_MINE_CONFLICT",
2527 svn_wc_conflict_choose_mine_conflict);
2528 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_MERGED",
2529 svn_wc_conflict_choose_merged);
2532 PyModule_AddIntConstant(mod, "STATUS_NONE", svn_wc_status_none);
2533 PyModule_AddIntConstant(mod, "STATUS_UNVERSIONED", svn_wc_status_unversioned);
2534 PyModule_AddIntConstant(mod, "STATUS_NORMAL", svn_wc_status_normal);
2535 PyModule_AddIntConstant(mod, "STATUS_ADDED", svn_wc_status_added);
2536 PyModule_AddIntConstant(mod, "STATUS_MISSING", svn_wc_status_missing);
2537 PyModule_AddIntConstant(mod, "STATUS_DELETED", svn_wc_status_deleted);
2538 PyModule_AddIntConstant(mod, "STATUS_REPLACED", svn_wc_status_replaced);
2539 PyModule_AddIntConstant(mod, "STATUS_MODIFIED", svn_wc_status_modified);
2540 PyModule_AddIntConstant(mod, "STATUS_MERGED", svn_wc_status_merged);
2541 PyModule_AddIntConstant(mod, "STATUS_CONFLICTED", svn_wc_status_conflicted);
2542 PyModule_AddIntConstant(mod, "STATUS_IGNORED", svn_wc_status_ignored);
2543 PyModule_AddIntConstant(mod, "STATUS_OBSTRUCTED", svn_wc_status_obstructed);
2544 PyModule_AddIntConstant(mod, "STATUS_EXTERNAL", svn_wc_status_external);
2545 PyModule_AddIntConstant(mod, "STATUS_INCOMPLETE", svn_wc_status_incomplete);
2547 PyModule_AddIntConstant(mod, "TRANSLATE_FROM_NF", SVN_WC_TRANSLATE_FROM_NF);
2548 PyModule_AddIntConstant(mod, "TRANSLATE_TO_NF", SVN_WC_TRANSLATE_TO_NF);
2549 PyModule_AddIntConstant(mod, "TRANSLATE_FORCE_EOL_REPAIR", SVN_WC_TRANSLATE_FORCE_EOL_REPAIR);
2550 PyModule_AddIntConstant(mod, "TRANSLATE_NO_OUTPUT_CLEANUP", SVN_WC_TRANSLATE_NO_OUTPUT_CLEANUP);
2551 PyModule_AddIntConstant(mod, "TRANSLATE_FORCE_COPY", SVN_WC_TRANSLATE_FORCE_COPY);
2552 PyModule_AddIntConstant(mod, "TRANSLATE_USE_GLOBAL_TMP", SVN_WC_TRANSLATE_USE_GLOBAL_TMP);
2554 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_POSTPONE", svn_wc_conflict_choose_postpone);
2555 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_BASE", svn_wc_conflict_choose_base);
2556 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_THEIRS_FULL", svn_wc_conflict_choose_theirs_full);
2557 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_MINE_FULL", svn_wc_conflict_choose_mine_full);
2558 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_THEIRS_CONFLICT", svn_wc_conflict_choose_theirs_conflict);
2559 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_MINE_CONFLICT", svn_wc_conflict_choose_mine_conflict);
2560 PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_MERGED", svn_wc_conflict_choose_merged);
2562 PyModule_AddObject(mod, "WorkingCopy", (PyObject *)&Adm_Type);
2563 Py_INCREF(&Adm_Type);
2565 PyModule_AddObject(mod, "CommittedQueue", (PyObject *)&CommittedQueue_Type);
2566 Py_INCREF(&CommittedQueue_Type);