Make lock function available for older versions of svn.
[jelmer/subvertpy.git] / subvertpy / wc.c
index be9a8d716c415cc52b5df06c87bcf438267b79c6..b0d2445d2c980b711aacac473ec79f4ebe91e294 100644 (file)
@@ -24,6 +24,8 @@
 #include <structmember.h>
 #include <stdbool.h>
 #include <apr_md5.h>
+#include <apr_sha1.h>
+#include <fcntl.h>
 
 #include "util.h"
 #include "editor.h"
 #define T_BOOL T_BYTE
 #endif
 
-#if ONLY_SINCE_SVN(1, 5)
-#define REPORTER_T svn_ra_reporter3_t
-#else
-#define REPORTER_T svn_ra_reporter2_t
-#endif
-
-static PyTypeObject Entry_Type;
-static PyTypeObject Status_Type;
-static PyTypeObject Adm_Type;
+typedef struct {
+    PyObject_HEAD
+    svn_lock_t lock;
+    apr_pool_t *pool;
+} LockObject;
 
-static PyObject *py_entry(const svn_wc_entry_t *entry);
-static PyObject *py_status(const svn_wc_status2_t *status);
+#if ONLY_SINCE_SVN(1, 7)
+typedef struct {
+    PyObject_VAR_HEAD
+    apr_pool_t *pool;
+    svn_wc_context_t *context;
+} ContextObject;
+static PyTypeObject Context_Type;
+#endif
 
 #if ONLY_BEFORE_SVN(1, 5)
 struct svn_wc_committed_queue_t
 {
-       apr_pool_t *pool;
-       apr_array_header_t *queue;
-       svn_boolean_t have_recursive;
+    apr_pool_t *pool;
+    apr_array_header_t *queue;
+    svn_boolean_t have_recursive;
 };
 
-#if SVN_VER_MINOR < 5
-typedef struct svn_wc_committed_queue_t svn_wc_committed_queue_t;
-#endif
-
 typedef struct
 {
-       const char *path;
-       svn_wc_adm_access_t *adm_access;
-       svn_boolean_t recurse;
-       svn_boolean_t remove_lock;
-       apr_array_header_t *wcprop_changes;
-       unsigned char *digest;
+    const char *path;
+    svn_wc_adm_access_t *adm_access;
+    svn_boolean_t recurse;
+    svn_boolean_t remove_lock;
+    apr_array_header_t *wcprop_changes;
+    unsigned char *digest;
 } committed_queue_item_t;
 
-#if SVN_VER_MINOR < 5
-static
-#endif
 svn_wc_committed_queue_t *svn_wc_committed_queue_create(apr_pool_t *pool)
 {
-       svn_wc_committed_queue_t *q;
+    svn_wc_committed_queue_t *q;
 
-       q = apr_palloc(pool, sizeof(*q));
-       q->pool = pool;
-       q->queue = apr_array_make(pool, 1, sizeof(committed_queue_item_t *));
-       q->have_recursive = FALSE;
+    q = apr_palloc(pool, sizeof(*q));
+    q->pool = pool;
+    q->queue = apr_array_make(pool, 1, sizeof(committed_queue_item_t *));
+    q->have_recursive = FALSE;
 
-       return q;
+    return q;
 }
 
-#if SVN_VER_MINOR < 5
-static
-#endif
 svn_error_t *svn_wc_queue_committed(svn_wc_committed_queue_t **queue,
                         const char *path,
                         svn_wc_adm_access_t *adm_access,
@@ -121,129 +115,159 @@ svn_error_t *svn_wc_queue_committed(svn_wc_committed_queue_t **queue,
 #endif
 
 typedef struct {
-       PyObject_VAR_HEAD
-       apr_pool_t *pool;
-       svn_wc_committed_queue_t *queue;
+    PyObject_VAR_HEAD
+    apr_pool_t *pool;
+    svn_wc_committed_queue_t *queue;
 } CommittedQueueObject;
-static PyTypeObject CommittedQueue_Type;
-
-#if ONLY_SINCE_SVN(1, 5)
-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)
-{
-       PyObject *self = (PyObject *)baton, *py_lock_token, *ret;
-       PyGILState_STATE state = PyGILState_Ensure();
-       if (lock_token == NULL) {
-               py_lock_token = Py_None;
-               Py_INCREF(py_lock_token);
-       } else {
-               py_lock_token = PyBytes_FromString(lock_token);
-       }
-       ret = PyObject_CallMethod(self, "set_path", "slbOi", path, revision, start_empty, py_lock_token, depth);
-       Py_DECREF(py_lock_token);
-       CB_CHECK_PYRETVAL(ret);
-       Py_DECREF(ret);
-       PyGILState_Release(state);
-       return NULL;
-}
-
-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)
-{
-       PyObject *self = (PyObject *)report_baton, *ret, *py_lock_token;
-       PyGILState_STATE state = PyGILState_Ensure();
-       if (lock_token == NULL) {
-               py_lock_token = Py_None;
-               Py_INCREF(py_lock_token);
-       } else {
-               py_lock_token = PyBytes_FromString(lock_token);
-       }
-       ret = PyObject_CallMethod(self, "link_path", "sslbOi", path, url, revision, start_empty, py_lock_token, depth);
-       Py_DECREF(py_lock_token);
-       CB_CHECK_PYRETVAL(ret);
-       Py_DECREF(ret);
-       PyGILState_Release(state);
-       return NULL;
-}
 
-
-#else
-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)
+svn_wc_committed_queue_t *PyObject_GetCommittedQueue(PyObject *obj)
 {
-       PyObject *self = (PyObject *)baton, *py_lock_token, *ret;
-       PyGILState_STATE state = PyGILState_Ensure();
-       if (lock_token == NULL) {
-               py_lock_token = Py_None;
-               Py_INCREF(py_lock_token);
-       } else {
-               py_lock_token = PyBytes_FromString(lock_token);
-       }
-       ret = PyObject_CallMethod(self, "set_path", "slbOi", path, revision, start_empty, py_lock_token, svn_depth_infinity);
-       CB_CHECK_PYRETVAL(ret);
-       Py_DECREF(ret);
-       PyGILState_Release(state);
-       return NULL;
+    return ((CommittedQueueObject *)obj)->queue;
 }
 
-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)
-{
-       PyObject *self = (PyObject *)report_baton, *ret, *py_lock_token;
-       PyGILState_STATE state = PyGILState_Ensure();
-       if (lock_token == NULL) {
-               py_lock_token = Py_None;
-               Py_INCREF(py_lock_token);
-       } else {
-               py_lock_token = PyBytes_FromString(lock_token);
-       }
-       ret = PyObject_CallMethod(self, "link_path", "sslbOi", path, url, revision, start_empty, py_lock_token, svn_depth_infinity);
-       CB_CHECK_PYRETVAL(ret);
-       Py_DECREF(ret);
-       PyGILState_Release(state);
-       return NULL;
+#if ONLY_SINCE_SVN(1, 5)
+static svn_error_t *py_ra_report3_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)
+{
+    PyObject *self = (PyObject *)baton, *py_lock_token, *ret;
+    PyGILState_STATE state = PyGILState_Ensure();
+    if (lock_token == NULL) {
+        py_lock_token = Py_None;
+        Py_INCREF(py_lock_token);
+    } else {
+        py_lock_token = PyBytes_FromString(lock_token);
+    }
+    ret = PyObject_CallMethod(self, "set_path", "slbOi", path, revision,
+                              start_empty, py_lock_token, depth);
+    Py_DECREF(py_lock_token);
+    CB_CHECK_PYRETVAL(ret);
+    Py_DECREF(ret);
+    PyGILState_Release(state);
+    return NULL;
+}
+
+static svn_error_t *py_ra_report3_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)
+{
+    PyObject *self = (PyObject *)report_baton, *ret, *py_lock_token;
+    PyGILState_STATE state = PyGILState_Ensure();
+    if (lock_token == NULL) {
+        py_lock_token = Py_None;
+        Py_INCREF(py_lock_token);
+    } else {
+        py_lock_token = PyBytes_FromString(lock_token);
+    }
+    ret = PyObject_CallMethod(self, "link_path", "sslbOi", path, url, revision,
+                              start_empty, py_lock_token, depth);
+    Py_DECREF(py_lock_token);
+    CB_CHECK_PYRETVAL(ret);
+    Py_DECREF(ret);
+    PyGILState_Release(state);
+    return NULL;
 }
 
-
 #endif
 
-static svn_error_t *py_ra_report_delete_path(void *baton, const char *path, apr_pool_t *pool)
-{
-       PyObject *self = (PyObject *)baton, *ret;
-       PyGILState_STATE state = PyGILState_Ensure();
-       ret = PyObject_CallMethod(self, "delete_path", "s", path);
-       CB_CHECK_PYRETVAL(ret);
-       Py_DECREF(ret);
-       PyGILState_Release(state);
-       return NULL;
+static svn_error_t *py_ra_report2_set_path(void *baton, const char *path,
+                                           svn_revnum_t revision,
+                                           int start_empty, const char *lock_token,
+                                           apr_pool_t *pool)
+{
+    PyObject *self = (PyObject *)baton, *py_lock_token, *ret;
+    PyGILState_STATE state = PyGILState_Ensure();
+    if (lock_token == NULL) {
+        py_lock_token = Py_None;
+        Py_INCREF(py_lock_token);
+    } else {
+        py_lock_token = PyBytes_FromString(lock_token);
+    }
+    ret = PyObject_CallMethod(self, "set_path", "slbOi", path, revision,
+                              start_empty, py_lock_token, svn_depth_infinity);
+    CB_CHECK_PYRETVAL(ret);
+    Py_DECREF(ret);
+    PyGILState_Release(state);
+    return NULL;
+}
+
+static svn_error_t *py_ra_report2_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)
+{
+    PyObject *self = (PyObject *)report_baton, *ret, *py_lock_token;
+    PyGILState_STATE state = PyGILState_Ensure();
+    if (lock_token == NULL) {
+        py_lock_token = Py_None;
+        Py_INCREF(py_lock_token);
+    } else {
+        py_lock_token = PyBytes_FromString(lock_token);
+    }
+    ret = PyObject_CallMethod(self, "link_path", "sslbOi", path, url, revision,
+                              start_empty, py_lock_token, svn_depth_infinity);
+    CB_CHECK_PYRETVAL(ret);
+    Py_DECREF(ret);
+    PyGILState_Release(state);
+    return NULL;
+}
+
+static svn_error_t *py_ra_report_delete_path(void *baton, const char *path,
+                                             apr_pool_t *pool)
+{
+    PyObject *self = (PyObject *)baton, *ret;
+    PyGILState_STATE state = PyGILState_Ensure();
+    ret = PyObject_CallMethod(self, "delete_path", "s", path);
+    CB_CHECK_PYRETVAL(ret);
+    Py_DECREF(ret);
+    PyGILState_Release(state);
+    return NULL;
 }
 
 static svn_error_t *py_ra_report_finish(void *baton, apr_pool_t *pool)
 {
-       PyObject *self = (PyObject *)baton, *ret;
-       PyGILState_STATE state = PyGILState_Ensure();
-       ret = PyObject_CallMethod(self, "finish", "");
-       CB_CHECK_PYRETVAL(ret);
-       Py_DECREF(ret);
-       PyGILState_Release(state);
-       return NULL;
+    PyObject *self = (PyObject *)baton, *ret;
+    PyGILState_STATE state = PyGILState_Ensure();
+    ret = PyObject_CallMethod(self, "finish", "");
+    CB_CHECK_PYRETVAL(ret);
+    Py_DECREF(ret);
+    PyGILState_Release(state);
+    return NULL;
 }
 
 static svn_error_t *py_ra_report_abort(void *baton, apr_pool_t *pool)
 {
-       PyObject *self = (PyObject *)baton, *ret;
-       PyGILState_STATE state = PyGILState_Ensure();
-       ret = PyObject_CallMethod(self, "abort", "");
-       CB_CHECK_PYRETVAL(ret);
-       Py_DECREF(ret);
-       PyGILState_Release(state);
-       return NULL;
+    PyObject *self = (PyObject *)baton, *ret;
+    PyGILState_STATE state = PyGILState_Ensure();
+    ret = PyObject_CallMethod(self, "abort", "");
+    CB_CHECK_PYRETVAL(ret);
+    Py_DECREF(ret);
+    PyGILState_Release(state);
+    return NULL;
 }
 
-static const REPORTER_T py_ra_reporter = {
-       py_ra_report_set_path,
-       py_ra_report_delete_path,
-       py_ra_report_link_path,
-       py_ra_report_finish,
-       py_ra_report_abort,
+#if ONLY_SINCE_SVN(1, 5)
+const svn_ra_reporter3_t py_ra_reporter3 = {
+    py_ra_report3_set_path,
+    py_ra_report_delete_path,
+    py_ra_report3_link_path,
+    py_ra_report_finish,
+    py_ra_report_abort,
 };
+#endif
 
+const svn_ra_reporter2_t py_ra_reporter2 = {
+    py_ra_report2_set_path,
+    py_ra_report_delete_path,
+    py_ra_report2_link_path,
+    py_ra_report_finish,
+    py_ra_report_abort,
+};
 
 
 /**
@@ -272,57 +296,6 @@ static PyObject *api_version(PyObject *self)
                                                 ver->patch, ver->tag);
 }
 
-static svn_error_t *py_wc_found_entry(const char *path, const svn_wc_entry_t *entry, void *walk_baton, apr_pool_t *pool)
-{
-       PyObject *fn, *ret;
-       PyObject *callbacks = (PyObject *)walk_baton;
-       PyGILState_STATE state = PyGILState_Ensure();
-       if (PyTuple_Check(callbacks)) {
-               fn = PyTuple_GET_ITEM(callbacks, 0);
-       } else {
-               fn = (PyObject *)walk_baton;
-       }
-       ret = PyObject_CallFunction(fn, "sO", path, py_entry(entry));
-       CB_CHECK_PYRETVAL(ret);
-       Py_DECREF(ret);
-       PyGILState_Release(state);
-       return NULL;
-}
-
-#if ONLY_SINCE_SVN(1, 5)
-
-svn_error_t *py_wc_handle_error(const char *path, svn_error_t *err, void *walk_baton, apr_pool_t *pool)
-{
-       PyObject *fn, *ret;
-       PyObject *py_err;
-       PyGILState_STATE state;
-       PyObject *callbacks = (PyObject *)walk_baton;
-       if (PyTuple_Check(callbacks)) {
-               fn = PyTuple_GET_ITEM(callbacks, 1);
-       } else {
-               return err;
-       }
-       state = PyGILState_Ensure();
-       py_err = PyErr_NewSubversionException(err);
-       ret = PyObject_CallFunction(fn, "sO", path, py_err);
-       CB_CHECK_PYRETVAL(ret);
-       Py_DECREF(ret);
-       PyGILState_Release(state);
-       Py_DECREF(py_err);
-       return NULL;
-}
-
-static svn_wc_entry_callbacks2_t py_wc_entry_callbacks2 = {
-       py_wc_found_entry,
-       py_wc_handle_error,
-};
-#else
-static svn_wc_entry_callbacks_t py_wc_entry_callbacks = {
-       py_wc_found_entry
-};
-
-#endif
-
 
 void py_wc_notify_func(void *baton, const svn_wc_notify_t *notify, apr_pool_t *pool)
 {
@@ -331,1847 +304,542 @@ void py_wc_notify_func(void *baton, const svn_wc_notify_t *notify, apr_pool_t *p
                return;
 
        if (notify->err != NULL) {
+        PyGILState_STATE state = PyGILState_Ensure();
                PyObject *excval = PyErr_NewSubversionException(notify->err);
                ret = PyObject_CallFunction(func, "O", excval);
                Py_DECREF(excval);
                Py_XDECREF(ret);
                /* If ret was NULL, the cancel func should abort the operation. */
+        PyGILState_Release(state);
        }
 }
+bool py_dict_to_wcprop_changes(PyObject *dict, apr_pool_t *pool, apr_array_header_t **ret)
+{
+       PyObject *key, *val;
+       Py_ssize_t idx;
 
-typedef struct {
-       PyObject_VAR_HEAD
-       apr_pool_t *pool;
-       svn_wc_entry_t entry;
-} EntryObject;
+       if (dict == Py_None) {
+               *ret = NULL;
+               return true;
+       }
 
-static void entry_dealloc(PyObject *self)
-{
-       apr_pool_destroy(((EntryObject *)self)->pool);
-       PyObject_Del(self);
+       if (!PyDict_Check(dict)) {
+               PyErr_SetString(PyExc_TypeError, "Expected dictionary with property changes");
+               return false;
+       }
+
+       *ret = apr_array_make(pool, PyDict_Size(dict), sizeof(char *));
+
+       while (PyDict_Next(dict, &idx, &key, &val)) {
+               svn_prop_t *prop = apr_palloc(pool, sizeof(svn_prop_t));
+               prop->name = py_object_to_svn_string(key, pool);
+               if (prop->name == NULL) {
+                       return false;
+               }
+               if (val == Py_None) {
+                       prop->value = NULL;
+               } else {
+                       if (!PyBytes_Check(val)) {
+                               PyErr_SetString(PyExc_TypeError, "property values should be bytes");
+                               return false;
+                       }
+                       prop->value = svn_string_ncreate(PyBytes_AsString(val), PyBytes_Size(val), pool);
+               }
+               APR_ARRAY_PUSH(*ret, svn_prop_t *) = prop;
+       }
+
+       return true;
 }
 
-static PyMemberDef entry_members[] = {
-       { "name", T_STRING, offsetof(EntryObject, entry.name), READONLY,
-               "Name of the file"},
-       { "copyfrom_url", T_STRING, offsetof(EntryObject, entry.copyfrom_url), READONLY,
-               "Copyfrom location" },
-       { "copyfrom_rev", T_LONG, offsetof(EntryObject, entry.copyfrom_rev), READONLY,
-               "Copyfrom revision" },
-       { "uuid", T_STRING, offsetof(EntryObject, entry.uuid), READONLY,
-               "UUID of repository" },
-       { "url", T_STRING, offsetof(EntryObject, entry.url), READONLY,
-               "URL in repository" },
-       { "repos", T_STRING, offsetof(EntryObject, entry.repos), READONLY,
-               "Canonical repository URL" },
-       { "schedule", T_INT, offsetof(EntryObject, entry.schedule), READONLY,
-               "Scheduling (add, replace, delete, etc)" },
-       { "kind", T_INT, offsetof(EntryObject, entry.kind), READONLY,
-               "Kind of file (file, dir, etc)" },
-       { "revision", T_LONG, offsetof(EntryObject, entry.revision), READONLY,
-               "Base revision", },
-       { "cmt_rev", T_LONG, offsetof(EntryObject, entry.cmt_rev), READONLY,
-               "Last revision this was changed" },
-       { "checksum", T_STRING, offsetof(EntryObject, entry.checksum), READONLY,
-               "Hex MD5 checksum for the untranslated text base file" },
-       { "cmt_date", T_LONG, offsetof(EntryObject, entry.cmt_date), READONLY,
-               "Last date this was changed" },
-       { "cmt_author", T_STRING, offsetof(EntryObject, entry.cmt_author), READONLY,
-               "Last commit author of this item" },
-       { NULL, }
-};
+#if ONLY_SINCE_SVN(1, 6)
+svn_error_t *wc_validator3(void *baton, const char *uuid, const char *url, const char *root_url, apr_pool_t *pool)
+{
+       PyObject *py_validator = baton, *ret;
+    PyGILState_STATE state;
 
-static PyTypeObject Entry_Type = {
-       PyVarObject_HEAD_INIT(NULL, 0)
-       "wc.Entry", /*  const char *tp_name;  For printing, in format "<module>.<name>" */
-       sizeof(EntryObject),
-       0,/*    Py_ssize_t tp_basicsize, tp_itemsize;  For allocation */
+       if (py_validator == Py_None) {
+               return NULL;
+       }
+    state = PyGILState_Ensure();
+       ret = PyObject_CallFunction(py_validator, "sss", uuid, url, root_url);
+       if (ret == NULL) {
+        PyGILState_Release(state);
+               return py_svn_error();
+       }
 
-       /* Methods to implement standard operations */
+       Py_DECREF(ret);
 
-       entry_dealloc, /*       destructor tp_dealloc;  */
-       NULL, /*        printfunc tp_print;     */
-       NULL, /*        getattrfunc tp_getattr; */
-       NULL, /*        setattrfunc tp_setattr; */
-       NULL, /*        cmpfunc tp_compare;     */
-       NULL, /*        reprfunc tp_repr;       */
+    PyGILState_Release(state);
+       return NULL;
+}
 
-       /* Method suites for standard classes */
+#endif
 
-       NULL, /*        PyNumberMethods *tp_as_number;  */
-       NULL, /*        PySequenceMethods *tp_as_sequence;      */
-       NULL, /*        PyMappingMethods *tp_as_mapping;        */
+svn_error_t *wc_validator2(void *baton, const char *uuid, const char *url, svn_boolean_t root, apr_pool_t *pool)
+{
+       PyObject *py_validator = baton, *ret;
+    PyGILState_STATE state;
 
-       /* More standard operations (here for binary compatibility) */
+       if (py_validator == Py_None) {
+               return NULL;
+       }
 
-       NULL, /*        hashfunc tp_hash;       */
-       NULL, /*        ternaryfunc tp_call;    */
-       NULL, /*        reprfunc tp_str;        */
-       NULL, /*        getattrofunc tp_getattro;       */
-       NULL, /*        setattrofunc tp_setattro;       */
+    state = PyGILState_Ensure();
+       ret = PyObject_CallFunction(py_validator, "ssO", uuid, url, Py_None);
+       if (ret == NULL) {
+        PyGILState_Release(state);
+               return py_svn_error();
+       }
 
-       /* Functions to access object as input/output buffer */
-       NULL, /*        PyBufferProcs *tp_as_buffer;    */
+       Py_DECREF(ret);
+    PyGILState_Release(state);
 
-       /* Flags to define presence of optional/expanded features */
-       0, /*   long tp_flags;  */
+       return NULL;
+}
 
-       NULL, /*        const char *tp_doc;  Documentation string */
+static PyObject *get_actual_target(PyObject *self, PyObject *args)
+{
+       const char *path;
+       const char *anchor = NULL, *target = NULL;
+       apr_pool_t *temp_pool;
+       PyObject *ret, *py_path;
 
-       /* Assigned meaning in release 2.0 */
-       /* call function for all accessible objects */
-       NULL, /*        traverseproc tp_traverse;       */
+       if (!PyArg_ParseTuple(args, "O", &py_path))
+               return NULL;
 
-       /* delete references to contained objects */
-       NULL, /*        inquiry tp_clear;       */
+       temp_pool = Pool(NULL);
+       if (temp_pool == NULL) {
+               return NULL;
+       }
 
-       /* Assigned meaning in release 2.1 */
-       /* rich comparisons */
-       NULL, /*        richcmpfunc tp_richcompare;     */
+       path = py_object_to_svn_dirent(py_path, temp_pool);
+       if (path == NULL) {
+               apr_pool_destroy(temp_pool);
+               return NULL;
+       }
 
-       /* weak reference enabler */
-       0, /*   Py_ssize_t tp_weaklistoffset;   */
+       RUN_SVN_WITH_POOL(temp_pool,
+                 svn_wc_get_actual_target(path,
+                                                                  &anchor, &target, temp_pool));
 
-       /* Added in release 2.2 */
-       /* Iterators */
-       NULL, /*        getiterfunc tp_iter;    */
-       NULL, /*        iternextfunc tp_iternext;       */
+       ret = Py_BuildValue("(ss)", anchor, target);
 
-       /* Attribute descriptor and subclassing stuff */
-       NULL, /*        struct PyMethodDef *tp_methods; */
-       entry_members, /*       struct PyMemberDef *tp_members; */
+       apr_pool_destroy(temp_pool);
 
-};
+       return ret;
+}
 
-static PyObject *py_entry(const svn_wc_entry_t *entry)
+/**
+ * Determine the revision status of a specified working copy.
+ *
+ * :return: Tuple with minimum and maximum revnums found, whether the
+ * working copy was switched and whether it was modified.
+ */
+static PyObject *revision_status(PyObject *self, PyObject *args, PyObject *kwargs)
 {
-       EntryObject *ret;
+       char *kwnames[] = { "wc_path", "trail_url", "committed",  NULL };
+       const char *wc_path;
+       char *trail_url=NULL;
+       bool committed=false;
+       PyObject *ret, *py_wc_path;
+       svn_wc_revision_status_t *revstatus;
+       apr_pool_t *temp_pool;
 
-       ret = PyObject_New(EntryObject, &Entry_Type);
-       if (ret == NULL)
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|zb", kwnames, &py_wc_path,
+                                                                        &trail_url, &committed))
                return NULL;
 
-       ret->pool = Pool(NULL);
-       if (ret->pool == NULL)
+       temp_pool = Pool(NULL);
+       if (temp_pool == NULL) {
                return NULL;
-       ret->entry = *svn_wc_entry_dup(entry, ret->pool);
-       return (PyObject *)ret;
-}
+       }
 
-typedef struct {
-       PyObject_VAR_HEAD
-       apr_pool_t *pool;
-       svn_wc_status2_t status;
-       PyObject *entry;
-} StatusObject;
+       wc_path = py_object_to_svn_dirent(py_wc_path, temp_pool);
+       if (wc_path == NULL) {
+               apr_pool_destroy(temp_pool);
+               return NULL;
+       }
+       RUN_SVN_WITH_POOL(temp_pool,
+                       svn_wc_revision_status(
+                               &revstatus, wc_path, trail_url,
+                                committed, py_cancel_check, NULL, temp_pool));
+       ret = Py_BuildValue("(llbb)", revstatus->min_rev, revstatus->max_rev,
+                       revstatus->switched, revstatus->modified);
+       apr_pool_destroy(temp_pool);
+       return ret;
+}
 
-static void status_dealloc(PyObject *self)
+static PyObject *is_normal_prop(PyObject *self, PyObject *args)
 {
-       apr_pool_destroy(((StatusObject *)self)->pool);
-       Py_XDECREF(((StatusObject *)self)->entry);
-       PyObject_Del(self);
-}
+       char *name;
 
-static PyMemberDef status_members[] = {
-       { "entry", T_OBJECT, offsetof(StatusObject, entry), READONLY,
-               "Can be NULL if not under version control." },
-       { "locked", T_BOOL, offsetof(StatusObject, status.locked), READONLY,
-               "a directory can be 'locked' if a working copy update was interrupted." },
-       { "copied", T_BOOL, offsetof(StatusObject, status.copied), READONLY,
-               "a file or directory can be 'copied' if it's scheduled for addition-with-history (or part of a subtree that is scheduled as such.)." },
-       { "switched", T_BOOL, offsetof(StatusObject, status.switched), READONLY,
-               "a file or directory can be 'switched' if the switch command has been used." },
-       { "url", T_STRING, offsetof(StatusObject, status.url), READONLY,
-               "URL (actual or expected) in repository" },
-       { "revision", T_LONG, offsetof(StatusObject, status.ood_last_cmt_rev), READONLY,
-               "Set to the youngest committed revision, or SVN_INVALID_REVNUM if not out of date.", },
-       { "kind", T_INT, offsetof(StatusObject, status.ood_kind), READONLY,
-               "Set to the node kind of the youngest commit, or svn_node_none if not out of date.", },
-       { "status", T_INT, offsetof(StatusObject, status.text_status), READONLY,
-               "The status of the entry.", },
-       { NULL, }
-};
+       if (!PyArg_ParseTuple(args, "s", &name))
+               return NULL;
 
-static PyTypeObject Status_Type = {
-       PyVarObject_HEAD_INIT(NULL, 0)
-       "wc.Status", /* const char *tp_name;  For printing, in format "<module>.<name>" */
-       sizeof(StatusObject),
-       0,/*    Py_ssize_t tp_basicsize, tp_itemsize;  For allocation */
+       return PyBool_FromLong(svn_wc_is_normal_prop(name));
+}
 
-       /* Methods to implement standard operations */
+static PyObject *is_adm_dir(PyObject *self, PyObject *args)
+{
+       char *name;
+       apr_pool_t *pool;
+       svn_boolean_t ret;
 
-       status_dealloc, /*      destructor tp_dealloc;  */
-       NULL, /*        printfunc tp_print;     */
-       NULL, /*        getattrfunc tp_getattr; */
-       NULL, /*        setattrfunc tp_setattr; */
-       NULL, /*        cmpfunc tp_compare;     */
-       NULL, /*        reprfunc tp_repr;       */
+       if (!PyArg_ParseTuple(args, "s", &name))
+               return NULL;
 
-       /* Method suites for standard classes */
-
-       NULL, /*        PyNumberMethods *tp_as_number;  */
-       NULL, /*        PySequenceMethods *tp_as_sequence;      */
-       NULL, /*        PyMappingMethods *tp_as_mapping;        */
-
-       /* More standard operations (here for binary compatibility) */
-
-       NULL, /*        hashfunc tp_hash;       */
-       NULL, /*        ternaryfunc tp_call;    */
-       NULL, /*        reprfunc tp_str;        */
-       NULL, /*        getattrofunc tp_getattro;       */
-       NULL, /*        setattrofunc tp_setattro;       */
-
-       /* Functions to access object as input/output buffer */
-       NULL, /*        PyBufferProcs *tp_as_buffer;    */
-
-       /* Flags to define presence of optional/expanded features */
-       0, /*   long tp_flags;  */
-
-       "Working copy status object", /*        const char *tp_doc;  Documentation string */
-
-       /* Assigned meaning in release 2.0 */
-       /* call function for all accessible objects */
-       NULL, /*        traverseproc tp_traverse;       */
-
-       /* delete references to contained objects */
-       NULL, /*        inquiry tp_clear;       */
-
-       /* Assigned meaning in release 2.1 */
-       /* rich comparisons */
-       NULL, /*        richcmpfunc tp_richcompare;     */
-
-       /* weak reference enabler */
-       0, /*   Py_ssize_t tp_weaklistoffset;   */
-
-       /* Added in release 2.2 */
-       /* Iterators */
-       NULL, /*        getiterfunc tp_iter;    */
-       NULL, /*        iternextfunc tp_iternext;       */
-
-       /* Attribute descriptor and subclassing stuff */
-       NULL, /*        struct PyMethodDef *tp_methods; */
-       status_members, /*      struct PyMemberDef *tp_members; */
-
-};
-
-static PyObject *py_status(const svn_wc_status2_t *status)
-{
-       StatusObject *ret;
-       svn_wc_status2_t *dup_status;
-
-       ret = PyObject_New(StatusObject, &Status_Type);
-       if (ret == NULL)
+       pool = Pool(NULL);
+       if (pool == NULL)
                return NULL;
 
-       ret->pool = Pool(NULL);
-       if (ret->pool == NULL) {
-               PyObject_Del(ret);
-               return NULL;
-       }
+       ret = svn_wc_is_adm_dir(name, pool);
 
-       dup_status = svn_wc_dup_status2(status, ret->pool);
-       if (dup_status == NULL)
-       {
-               PyErr_NoMemory();
-               return NULL;
-       }
-       ret->status = *dup_status;
+       apr_pool_destroy(pool);
 
-       ret->entry = py_entry(ret->status.entry);
-       return (PyObject *)ret;
+       return PyBool_FromLong(ret);
 }
 
-typedef struct {
-       PyObject_VAR_HEAD
-       svn_wc_adm_access_t *adm;
-       apr_pool_t *pool;
-} AdmObject;
-
-#define ADM_CHECK_CLOSED(adm_obj) \
-       if (adm_obj->adm == NULL) { \
-               PyErr_SetString(PyExc_RuntimeError, "WorkingCopy instance already closed"); \
-               return NULL; \
-       }
-
-static PyObject *adm_init(PyTypeObject *self, PyObject *args, PyObject *kwargs)
+static PyObject *is_wc_prop(PyObject *self, PyObject *args)
 {
-       PyObject *associated;
-       char *path;
-       bool write_lock=false;
-       int depth=0;
-       svn_wc_adm_access_t *parent_wc;
-       svn_error_t *err;
-       AdmObject *ret;
-       char *kwnames[] = { "associated", "path", "write_lock", "depth", NULL };
-
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os|bi", kwnames,
-                       &associated, &path, &write_lock, &depth))
-               return NULL;
-
-       ret = PyObject_New(AdmObject, &Adm_Type);
-       if (ret == NULL)
-               return NULL;
+       char *name;
 
-       ret->pool = Pool(NULL);
-       if (ret->pool == NULL)
-               return NULL;
-       if (associated == Py_None) {
-               parent_wc = NULL;
-       } else {
-               parent_wc = ((AdmObject *)associated)->adm;
-       }
-       Py_BEGIN_ALLOW_THREADS
-       err = svn_wc_adm_open3(&ret->adm, parent_wc,
-                                                  svn_dirent_canonicalize(path, ret->pool),
-                                                  write_lock, depth, py_cancel_check, NULL,
-                                                  ret->pool);
-       Py_END_ALLOW_THREADS
-
-       if (err != NULL) {
-               handle_svn_error(err);
-               svn_error_clear(err);
-               Py_DECREF(ret);
+       if (!PyArg_ParseTuple(args, "s", &name))
                return NULL;
-       }
 
-       return (PyObject *)ret;
+       return PyBool_FromLong(svn_wc_is_wc_prop(name));
 }
 
-static PyObject *adm_access_path(PyObject *self)
+static PyObject *is_entry_prop(PyObject *self, PyObject *args)
 {
-       AdmObject *admobj = (AdmObject *)self;
-       ADM_CHECK_CLOSED(admobj);
-       return py_object_from_svn_abspath(svn_wc_adm_access_path(admobj->adm));
-}
+       char *name;
 
-static PyObject *adm_locked(PyObject *self)
-{
-       AdmObject *admobj = (AdmObject *)self;
-       ADM_CHECK_CLOSED(admobj);
-       return PyBool_FromLong(svn_wc_adm_locked(admobj->adm));
+       if (!PyArg_ParseTuple(args, "s", &name))
+               return NULL;
+
+       return PyBool_FromLong(svn_wc_is_entry_prop(name));
 }
 
-static PyObject *adm_prop_get(PyObject *self, PyObject *args)
+static PyObject *get_adm_dir(PyObject *self)
 {
-       char *name, *path;
-       AdmObject *admobj = (AdmObject *)self;
-       const svn_string_t *value;
-       apr_pool_t *temp_pool;
+       apr_pool_t *pool;
        PyObject *ret;
-
-       if (!PyArg_ParseTuple(args, "ss", &name, &path))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
+       const char *dir;
+       pool = Pool(NULL);
+       if (pool == NULL)
                return NULL;
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_prop_get(&value, name, path, admobj->adm, temp_pool));
-       if (value == NULL || value->data == NULL) {
-               ret = Py_None;
-               Py_INCREF(ret);
-       } else {
-               ret = PyBytes_FromStringAndSize(value->data, value->len);
-       }
-       apr_pool_destroy(temp_pool);
+       dir = svn_wc_get_adm_dir(pool);
+       ret = py_object_from_svn_abspath(dir);
+       apr_pool_destroy(pool);
        return ret;
 }
 
-static PyObject *adm_prop_set(PyObject *self, PyObject *args)
+static PyObject *set_adm_dir(PyObject *self, PyObject *args)
 {
-       char *name, *value, *path;
-       AdmObject *admobj = (AdmObject *)self;
-       bool skip_checks=false;
        apr_pool_t *temp_pool;
-       int vallen;
-       svn_string_t *cvalue;
-       PyObject *notify_func = Py_None;
+       char *name;
+       PyObject *py_name;
 
-       if (!PyArg_ParseTuple(args, "sz#s|bO", &name, &value, &vallen, &path, &skip_checks,
-                                                 &notify_func))
+       if (!PyArg_ParseTuple(args, "O", &py_name))
                return NULL;
 
-       ADM_CHECK_CLOSED(admobj);
-
        temp_pool = Pool(NULL);
        if (temp_pool == NULL)
                return NULL;
-       if (value == NULL) {
-               cvalue = NULL;
-       } else {
-               cvalue = svn_string_ncreate(value, vallen, temp_pool);
+       name = py_object_to_svn_string(py_name, temp_pool);
+       if (name == NULL) {
+               apr_pool_destroy(temp_pool);
+               return NULL;
        }
-#if ONLY_SINCE_SVN(1, 6)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_prop_set3(name, cvalue, path, admobj->adm,
-                               skip_checks, py_wc_notify_func, (void *)notify_func,
-                               temp_pool));
-#else
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_prop_set2(name, cvalue, path, admobj->adm,
-                               skip_checks, temp_pool));
-#endif
+       RUN_SVN_WITH_POOL(temp_pool, svn_wc_set_adm_dir(name, temp_pool));
        apr_pool_destroy(temp_pool);
-
        Py_RETURN_NONE;
 }
 
-static PyObject *adm_entries_read(PyObject *self, PyObject *args)
+static PyObject *get_pristine_copy_path(PyObject *self, PyObject *args)
 {
-       apr_hash_t *entries;
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-       bool show_hidden=false;
-       apr_hash_index_t *idx;
-       const char *key;
-       apr_ssize_t klen;
-       svn_wc_entry_t *entry;
-       PyObject *py_entries, *obj;
+       apr_pool_t *pool;
+       const char *pristine_path;
+       const char *path;
+       PyObject *py_path;
+       PyObject *ret;
 
-       if (!PyArg_ParseTuple(args, "|b", &show_hidden))
+       if (!PyArg_ParseTuple(args, "O", &py_path))
                return NULL;
 
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
+       pool = Pool(NULL);
+       if (pool == NULL)
                return NULL;
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_entries_read(&entries, admobj->adm,
-                                show_hidden, temp_pool));
-       py_entries = PyDict_New();
-       if (py_entries == NULL) {
-               apr_pool_destroy(temp_pool);
+
+       path = py_object_to_svn_abspath(py_path, pool);
+       if (path == NULL) {
+               apr_pool_destroy(pool);
                return NULL;
        }
-       idx = apr_hash_first(temp_pool, entries);
-       while (idx != NULL) {
-               apr_hash_this(idx, (const void **)&key, &klen, (void **)&entry);
-               if (entry == NULL) {
-                       obj = Py_None;
-                       Py_INCREF(obj);
-               } else {
-                       obj = py_entry(entry);
-               }
-               PyDict_SetItemString(py_entries, key, obj);
-               Py_DECREF(obj);
-               idx = apr_hash_next(idx);
-       }
-       apr_pool_destroy(temp_pool);
-       return py_entries;
+
+       PyErr_WarnEx(PyExc_DeprecationWarning, "get_pristine_copy_path is deprecated. Use get_pristine_contents instead.", 2);
+       RUN_SVN_WITH_POOL(pool,
+                 svn_wc_get_pristine_copy_path(path,
+                                                                               &pristine_path, pool));
+       ret = py_object_from_svn_abspath(pristine_path);
+       apr_pool_destroy(pool);
+       return ret;
 }
 
-static PyObject *adm_walk_entries(PyObject *self, PyObject *args)
+static PyObject *get_pristine_contents(PyObject *self, PyObject *args)
 {
-       char *path;
-       PyObject *callbacks;
-       bool show_hidden=false;
+       const char *path;
        apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-       svn_depth_t depth = svn_depth_infinity;
+       PyObject *py_path;
+#if ONLY_SINCE_SVN(1, 6)
+       StreamObject *ret;
+       apr_pool_t *stream_pool;
+       svn_stream_t *stream;
+#else
+#if PY_MAJOR_VERSION >= 3
+       int fd;
+#endif
+       PyObject *ret;
+       const char *pristine_path;
+#endif
 
-       if (!PyArg_ParseTuple(args, "sO|bi", &path, &callbacks, &show_hidden, &depth))
+       if (!PyArg_ParseTuple(args, "O", &py_path))
                return NULL;
 
-       ADM_CHECK_CLOSED(admobj);
+#if ONLY_SINCE_SVN(1, 6)
+       stream_pool = Pool(NULL);
+       if (stream_pool == NULL)
+               return NULL;
 
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
+       temp_pool = Pool(stream_pool);
+       if (temp_pool == NULL) {
+               apr_pool_destroy(stream_pool);
                return NULL;
-#if ONLY_SINCE_SVN(1, 5)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_walk_entries3(
-                         svn_dirent_canonicalize(path, temp_pool), admobj->adm,
-                               &py_wc_entry_callbacks2, (void *)callbacks,
-                               depth, show_hidden, py_cancel_check, NULL,
-                               temp_pool));
+       }
 #else
-       if (depth != svn_depth_infinity) {
-               PyErr_SetString(PyExc_NotImplementedError,
-                                               "depth != infinity not supported for svn < 1.5");
-               apr_pool_destroy(temp_pool);
+       temp_pool = Pool(NULL);
+       if (temp_pool == NULL) {
                return NULL;
        }
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_walk_entries2(
-                         svn_dirent_canonicalize(path, temp_pool), admobj->adm,
-                               &py_wc_entry_callbacks, (void *)callbacks,
-                               show_hidden, py_cancel_check, NULL,
-                               temp_pool));
 #endif
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *adm_entry(PyObject *self, PyObject *args)
-{
-       char *path;
-       bool show_hidden=false;
-       apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-       const svn_wc_entry_t *entry;
-       PyObject *ret;
-
-       if (!PyArg_ParseTuple(args, "s|b", &path, &show_hidden))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
 
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
+       path = py_object_to_svn_abspath(py_path, temp_pool);
+       if (path == NULL) {
+               apr_pool_destroy(temp_pool);
                return NULL;
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_entry(&entry, svn_dirent_canonicalize(path, temp_pool), admobj->adm, show_hidden, temp_pool));
-
-       if (entry == NULL) {
-               PyErr_Format(PyExc_KeyError, "No such entry '%s'", path);
-               ret = NULL;
-       } else  {
-               ret = py_entry(entry);
        }
 
+#if ONLY_SINCE_SVN(1, 6)
+       RUN_SVN_WITH_POOL(stream_pool, svn_wc_get_pristine_contents(&stream, path, stream_pool, temp_pool));
        apr_pool_destroy(temp_pool);
-       return ret;
-}
 
-static PyObject *adm_get_prop_diffs(PyObject *self, PyObject *args)
-{
-       char *path;
-       apr_pool_t *temp_pool;
-       apr_array_header_t *propchanges;
-       apr_hash_t *original_props;
-       AdmObject *admobj = (AdmObject *)self;
-       svn_prop_t el;
-       int i;
-       PyObject *py_propchanges, *py_orig_props, *pyval;
+       if (stream == NULL) {
+               apr_pool_destroy(stream_pool);
+               Py_RETURN_NONE;
+       }
 
-       if (!PyArg_ParseTuple(args, "s", &path))
+       ret = PyObject_New(StreamObject, &Stream_Type);
+       if (ret == NULL)
                return NULL;
 
-       ADM_CHECK_CLOSED(admobj);
+       ret->pool = stream_pool;
+       ret->closed = FALSE;
+       ret->stream = stream;
 
+       return (PyObject *)ret;
+#else
        temp_pool = Pool(NULL);
        if (temp_pool == NULL)
                return NULL;
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_get_prop_diffs(&propchanges, &original_props,
-                               svn_dirent_canonicalize(path, temp_pool), admobj->adm, temp_pool));
-       py_propchanges = PyList_New(propchanges->nelts);
-       if (py_propchanges == NULL) {
+       RUN_SVN_WITH_POOL(temp_pool, svn_wc_get_pristine_copy_path(path, &pristine_path, temp_pool));
+#if PY_MAJOR_VERSION >= 3
+       fd = open(pristine_path, O_RDONLY);
+       if (fd < 0) {
+               PyErr_SetFromErrno(PyExc_IOError);
                apr_pool_destroy(temp_pool);
                return NULL;
        }
-       for (i = 0; i < propchanges->nelts; i++) {
-               el = APR_ARRAY_IDX(propchanges, i, svn_prop_t);
-               if (el.value != NULL)
-                       pyval = Py_BuildValue("(sz#)", el.name, el.value->data, el.value->len);
-               else
-                       pyval = Py_BuildValue("(sO)", el.name, Py_None);
-               if (pyval == NULL) {
-                       apr_pool_destroy(temp_pool);
-                       Py_DECREF(py_propchanges);
-                       return NULL;
-               }
-               if (PyList_SetItem(py_propchanges, i, pyval) != 0) {
-                       Py_DECREF(py_propchanges);
-                       apr_pool_destroy(temp_pool);
-                       return NULL;
-               }
-       }
-       py_orig_props = prop_hash_to_dict(original_props);
+       ret = PyFile_FromFd(fd, pristine_path, "rb", -1, NULL, NULL, NULL, true);
+#else
+       ret = PyFile_FromString((char *)pristine_path, "rb");
+#endif
        apr_pool_destroy(temp_pool);
-       if (py_orig_props == NULL) {
-               Py_DECREF(py_propchanges);
-               return NULL;
-       }
-       return Py_BuildValue("(NN)", py_propchanges, py_orig_props);
+       return ret;
+#endif
 }
 
-static PyObject *adm_add(PyObject *self, PyObject *args, PyObject *kwargs)
+static PyObject *ensure_adm(PyObject *self, PyObject *args, PyObject *kwargs)
 {
-       char *path, *copyfrom_url=NULL;
-       svn_revnum_t copyfrom_rev=-1;
-       char *kwnames[] = { "path", "copyfrom_url", "copyfrom_rev", "notify_func", "depth", NULL };
-       PyObject *notify_func=Py_None;
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-       svn_depth_t depth = svn_depth_infinity;
+       const char *path;
+       char *uuid, *url = NULL;
+       PyObject *py_path;
+       char *repos = NULL;
+       long rev = -1;
+       apr_pool_t *pool;
+       char *kwnames[] = { "path", "uuid", "url", "repos", "rev", "depth", NULL };
+       int depth = svn_depth_infinity;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zlOi", kwnames, &path,
-                       &copyfrom_url, &copyfrom_rev, &notify_func, &depth))
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oss|sli", kwnames,
+                                                                        &py_path, &uuid, &url, &repos, &rev, &depth))
                return NULL;
 
-       ADM_CHECK_CLOSED(admobj);
+       pool = Pool(NULL);
+       if (pool == NULL) {
+               return NULL;
+       }
 
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
+       path = py_object_to_svn_dirent(py_path, pool);
+       if (path == NULL) {
+               apr_pool_destroy(pool);
                return NULL;
+       }
 
-#if ONLY_SINCE_SVN(1, 6)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_add3(
-                                                  svn_dirent_canonicalize(path, temp_pool), admobj->adm,
-                                                  depth, svn_uri_canonicalize(copyfrom_url, temp_pool),
-                                                       copyfrom_rev, py_cancel_check, NULL,
-                                                       py_wc_notify_func,
-                                                       (void *)notify_func,
-                                                       temp_pool));
+#if ONLY_SINCE_SVN(1, 5)
+       RUN_SVN_WITH_POOL(pool,
+                                         svn_wc_ensure_adm3(path,
+                                                                                uuid, url, repos, rev, depth, pool));
 #else
        if (depth != svn_depth_infinity) {
-               PyErr_SetString(PyExc_NotImplementedError, "depth != infinity not supported on svn < 1.6");
-               apr_pool_destroy(temp_pool);
+               PyErr_SetString(PyExc_NotImplementedError,
+                                               "depth != infinity not supported with svn < 1.5");
+               apr_pool_destroy(pool);
                return NULL;
        }
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_add2(
-                                                  svn_dirent_canonicalize(path, temp_pool), admobj->adm, copyfrom_url,
-                                                       copyfrom_rev, py_cancel_check,
-                                                       py_wc_notify_func,
-                                                       (void *)notify_func,
-                                                       temp_pool));
+       RUN_SVN_WITH_POOL(pool,
+                                         svn_wc_ensure_adm2(path,
+                                                                                uuid, url, repos, rev, pool));
 #endif
-       apr_pool_destroy(temp_pool);
-
+       apr_pool_destroy(pool);
        Py_RETURN_NONE;
 }
 
-static PyObject *adm_copy(PyObject *self, PyObject *args)
+static PyObject *check_wc(PyObject *self, PyObject *args)
 {
-       AdmObject *admobj = (AdmObject *)self;
-       char *src, *dst;
-       PyObject *notify_func=Py_None;
-       apr_pool_t *temp_pool;
-
-       if (!PyArg_ParseTuple(args, "ss|O", &src, &dst, &notify_func))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_copy2(src, admobj->adm, dst,
-                                                       py_cancel_check, NULL,
-                                                       py_wc_notify_func, (void *)notify_func,
-                                                       temp_pool));
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *adm_delete(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-       char *kwnames[] = { "path", "notify_func", "keep_local",
-                               NULL };
-       char *path;
-       PyObject *notify_func=Py_None;
-       bool keep_local = false;
-
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Ob:delete", kwnames,
-                       &path, &notify_func, &keep_local))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-#if ONLY_SINCE_SVN(1, 5)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_delete3(path, admobj->adm,
-                                                       py_cancel_check, NULL,
-                                                       py_wc_notify_func, (void *)notify_func,
-                                                       keep_local,
-                                                       temp_pool));
-#else
-       if (keep_local) {
-               PyErr_SetString(PyExc_NotImplementedError,
-                                               "keep_local not supported on Subversion < 1.5");
-               return NULL;
-       }
-
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_delete2(path, admobj->adm,
-                                                       py_cancel_check, NULL,
-                                                       py_wc_notify_func, (void *)notify_func,
-                                                       temp_pool));
-#endif
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *adm_crawl_revisions(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-       char *path;
-       PyObject *reporter;
-       bool restore_files=true, recurse=true, use_commit_times=true;
-       PyObject *notify_func=Py_None;
-       apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-       svn_wc_traversal_info_t *traversal_info;
-       svn_boolean_t depth_compatibility_trick = FALSE;
-       svn_boolean_t honor_depth_exclude = FALSE;
-       char *kwnames[] = { "path", "reporter", "restore_files", "recurse", "use_commit_times", "notify_func", "depth_compatibility_trick", "honor_depth_exclude,", NULL };
-
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|bbbObb", kwnames, &path,
-                       &reporter, &restore_files, &recurse, &use_commit_times,
-                       &notify_func, &depth_compatibility_trick, &honor_depth_exclude))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-       traversal_info = svn_wc_init_traversal_info(temp_pool);
-#if ONLY_SINCE_SVN(1, 6)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_crawl_revisions4(svn_dirent_canonicalize(path, temp_pool), admobj->adm,
-                               &py_ra_reporter, (void *)reporter,
-                               restore_files, recurse?svn_depth_infinity:svn_depth_files,
-                               honor_depth_exclude,
-                               depth_compatibility_trick, use_commit_times,
-                               py_wc_notify_func, (void *)notify_func,
-                               traversal_info, temp_pool));
-#elif ONLY_SINCE_SVN(1, 5)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_crawl_revisions3(svn_dirent_canonicalize(path, temp_pool), admobj->adm,
-                               &py_ra_reporter, (void *)reporter,
-                               restore_files, recurse?svn_depth_infinity:svn_depth_files,
-                               depth_compatibility_trick, use_commit_times,
-                               py_wc_notify_func, (void *)notify_func,
-                               traversal_info, temp_pool));
-#else
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_crawl_revisions2(svn_dirent_canonicalize(path, temp_pool), admobj->adm,
-                               &py_ra_reporter, (void *)reporter,
-                               restore_files, recurse, use_commit_times,
-                               py_wc_notify_func, (void *)notify_func,
-                               traversal_info, temp_pool));
-#endif
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static void wc_done_handler(void *self)
-{
-       AdmObject *admobj = (AdmObject *)self;
-
-       Py_DECREF(admobj);
-}
-
-static PyObject *adm_get_update_editor(PyObject *self, PyObject *args)
-{
-       char *target;
-       bool use_commit_times=true, recurse=true;
-       PyObject * notify_func=Py_None;
-       char *diff3_cmd=NULL;
-       const svn_delta_editor_t *editor;
-       AdmObject *admobj = (AdmObject *)self;
-       void *edit_baton;
-       apr_pool_t *pool;
-       svn_revnum_t *latest_revnum;
-       svn_error_t *err;
-       svn_boolean_t allow_unver_obstructions = FALSE;
-       svn_boolean_t depth_is_sticky = FALSE;
-
-       if (!PyArg_ParseTuple(args, "s|bbOzbb", &target, &use_commit_times,
-                       &recurse, &notify_func, &diff3_cmd, &depth_is_sticky,
-                       &allow_unver_obstructions))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       pool = Pool(NULL);
-       if (pool == NULL)
-               return NULL;
-       latest_revnum = (svn_revnum_t *)apr_palloc(pool, sizeof(svn_revnum_t));
-       Py_BEGIN_ALLOW_THREADS
-#if ONLY_SINCE_SVN(1, 5)
-       /* FIXME: Support all values of depth */
-       /* FIXME: Support fetch_func */
-       /* FIXME: Support conflict func */
-       err = svn_wc_get_update_editor3(latest_revnum, admobj->adm, target,
-                               use_commit_times, recurse?svn_depth_infinity:svn_depth_files,
-                               depth_is_sticky, allow_unver_obstructions,
-                               py_wc_notify_func, (void *)notify_func,
-                               py_cancel_check, NULL,
-                               NULL, NULL, NULL, NULL,
-                               diff3_cmd, NULL, &editor, &edit_baton,
-                               NULL, pool);
-#else
-       if (allow_unver_obstructions) {
-               PyErr_SetString(PyExc_NotImplementedError,
-                                               "allow_unver_obstructions is not supported in svn < 1.5");
-               apr_pool_destroy(pool);
-               PyEval_RestoreThread(_save);
-               return NULL;
-       }
-       if (depth_is_sticky) {
-               PyErr_SetString(PyExc_NotImplementedError,
-                                               "depth_is_sticky is not supported in svn < 1.5");
-               apr_pool_destroy(pool);
-               PyEval_RestoreThread(_save);
-               return NULL;
-       }
-       err = svn_wc_get_update_editor2(latest_revnum, admobj->adm, target,
-                               use_commit_times, recurse, py_wc_notify_func, (void *)notify_func,
-                               py_cancel_check, NULL, diff3_cmd, &editor, &edit_baton,
-                               NULL, pool);
-#endif
-       Py_END_ALLOW_THREADS
-       if (err != NULL) {
-               handle_svn_error(err);
-               svn_error_clear(err);
-               apr_pool_destroy(pool);
-               return NULL;
-       }
-       Py_INCREF(admobj);
-       return new_editor_object(NULL, editor, edit_baton, pool, &Editor_Type,
-               wc_done_handler, admobj, NULL);
-}
-
-static bool py_dict_to_wcprop_changes(PyObject *dict, apr_pool_t *pool, apr_array_header_t **ret)
-{
-       PyObject *key, *val;
-       Py_ssize_t idx;
-
-       if (dict == Py_None) {
-               *ret = NULL;
-               return true;
-       }
-
-       if (!PyDict_Check(dict)) {
-               PyErr_SetString(PyExc_TypeError, "Expected dictionary with property changes");
-               return false;
-       }
-
-       *ret = apr_array_make(pool, PyDict_Size(dict), sizeof(char *));
-
-       while (PyDict_Next(dict, &idx, &key, &val)) {
-               svn_prop_t *prop = apr_palloc(pool, sizeof(svn_prop_t));
-               prop->name = py_object_to_svn_string(key, pool);
-               if (prop->name == NULL) {
-                       return false;
-               }
-               if (val == Py_None) {
-                       prop->value = NULL;
-               } else {
-                       if (!PyBytes_Check(val)) {
-                               PyErr_SetString(PyExc_TypeError, "property values should be bytes");
-                               return false;
-                       }
-                       prop->value = svn_string_ncreate(PyBytes_AsString(val), PyBytes_Size(val), pool);
-               }
-               APR_ARRAY_PUSH(*ret, svn_prop_t *) = prop;
-       }
-
-       return true;
-}
-
-static PyObject *adm_has_binary_prop(PyObject *self, PyObject *args)
-{
-       char *path;
-       svn_boolean_t binary;
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_has_binary_prop(&binary, path, admobj->adm, temp_pool));
-
-       apr_pool_destroy(temp_pool);
-
-       return PyBool_FromLong(binary);
-}
-
-static PyObject *adm_process_committed(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-       char *path, *rev_date = NULL, *rev_author = NULL;
-       bool recurse, remove_lock = false;
-       unsigned char *digest = NULL;
-       svn_revnum_t new_revnum;
-       PyObject *py_wcprop_changes = Py_None;
-       apr_array_header_t *wcprop_changes = NULL;
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-       int digest_len;
-       svn_boolean_t remove_changelist = FALSE;
-       char *kwnames[] = { "path", "recurse", "new_revnum", "rev_date", "rev_author",
-                                               "wcprop_changes", "remove_lock", "digest", "remove_changelist", NULL };
-
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sblzz|Obz#b", kwnames,
-                                                                        &path, &recurse, &new_revnum, &rev_date,
-                                                                        &rev_author, &py_wcprop_changes,
-                                                                        &remove_lock, &digest, &digest_len, &remove_changelist))
-               return NULL;
-
-       PyErr_WarnEx(PyExc_DeprecationWarning, "process_committed is deprecated. Use process_committed_queue instead.", 2);
-
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       if (!py_dict_to_wcprop_changes(py_wcprop_changes, temp_pool, &wcprop_changes)) {
-               apr_pool_destroy(temp_pool);
-               return NULL;
-       }
-
-#if ONLY_SINCE_SVN(1, 6)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_process_committed4(
-               svn_dirent_canonicalize(path, temp_pool), admobj->adm, recurse, new_revnum,
-                       rev_date, rev_author, wcprop_changes,
-                       remove_lock, remove_changelist, digest, temp_pool));
-#else
-       if (remove_changelist) {
-               PyErr_SetString(PyExc_NotImplementedError, "remove_changelist only supported in svn < 1.6");
-               apr_pool_destroy(temp_pool);
-               return NULL;
-       }
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_process_committed3(svn_dirent_canonicalize(path, temp_pool), admobj->adm, recurse, new_revnum,
-                                                                                                                  rev_date, rev_author, wcprop_changes,
-                                                                                                                  remove_lock, digest, temp_pool));
-#endif
-
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *adm_close(PyObject *self)
-{
-       AdmObject *admobj = (AdmObject *)self;
-       if (admobj->adm != NULL) {
-#if ONLY_SINCE_SVN(1, 6)
-               apr_pool_t *temp_pool = Pool(NULL);
-               Py_BEGIN_ALLOW_THREADS
-               svn_wc_adm_close2(admobj->adm, temp_pool);
-               apr_pool_destroy(temp_pool);
-#else
-               Py_BEGIN_ALLOW_THREADS
-               svn_wc_adm_close(admobj->adm);
-#endif
-               Py_END_ALLOW_THREADS
-               admobj->adm = NULL;
-       }
-
-       Py_RETURN_NONE;
-}
-
-static void adm_dealloc(PyObject *self)
-{
-       apr_pool_destroy(((AdmObject *)self)->pool);
-       PyObject_Del(self);
-}
-
-static PyObject *adm_repr(PyObject *self)
-{
-       AdmObject *admobj = (AdmObject *)self;
-
-       if (admobj->adm == NULL) {
-               return PyRepr_FromFormat("<wc.WorkingCopy (closed) at 0x%p>", admobj);
-       } else {
-               return PyRepr_FromFormat("<wc.WorkingCopy at '%s'>",
-                                                                  svn_wc_adm_access_path(admobj->adm));
-       }
-}
-
-static PyObject *adm_remove_lock(PyObject *self, PyObject *args)
-{
-       char *path;
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_remove_lock(path, admobj->adm, temp_pool))
-
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *get_ancestry(PyObject *self, PyObject *args)
-{
-       char *path;
-       char *url;
-       svn_revnum_t rev;
-       apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_get_ancestry(&url, &rev, path, admobj->adm, temp_pool));
-
-       apr_pool_destroy(temp_pool);
-
-       return Py_BuildValue("(si)", url, rev);
-}
-
-static PyObject *maybe_set_repos_root(PyObject *self, PyObject *args)
-{
-       char *path, *repos;
-       apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-
-       if (!PyArg_ParseTuple(args, "ss", &path, &repos))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_maybe_set_repos_root(admobj->adm, path, repos, temp_pool));
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *add_repos_file(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-       char *kwnames[] = { "dst_path", "new_base_contents", "new_contents",
-               "new_base_props", "new_props", "copyfrom_url", "copyfrom_rev",
-               "notify", NULL };
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-       char *dst_path, *copyfrom_url = NULL;
-       svn_revnum_t copyfrom_rev = -1;
-       PyObject *py_new_base_contents, *py_new_contents, *py_new_base_props,
-                        *py_new_props, *notify = Py_None;
-       svn_stream_t *new_contents, *new_base_contents;
-       apr_hash_t *new_props, *new_base_props;
-
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOOOO|zlO", kwnames,
-                       &dst_path, &py_new_base_contents, &py_new_contents, &py_new_base_props,
-                       &py_new_props, &copyfrom_url, &copyfrom_rev, &notify))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       new_base_props = prop_dict_to_hash(temp_pool, py_new_base_props);
-
-       new_props = prop_dict_to_hash(temp_pool, py_new_props);
-
-       new_base_contents = new_py_stream(temp_pool, py_new_base_contents);
-
-       new_contents = new_py_stream(temp_pool, py_new_contents);
-
-#if ONLY_SINCE_SVN(1, 6)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_add_repos_file3(dst_path, admobj->adm,
-                                                  new_base_contents,
-                                                  new_contents,
-                                                  new_base_props,
-                                                  new_props,
-                                                  copyfrom_url, copyfrom_rev,
-                                                  py_cancel_check, NULL,
-                                                  py_wc_notify_func, notify, temp_pool));
-#else
-       PyErr_SetString(PyExc_NotImplementedError,
-                                       "add_repos_file3 not supported on svn < 1.6");
-       apr_pool_destroy(temp_pool);
-#endif
-
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *mark_missing_deleted(PyObject *self, PyObject *args)
-{
-       char *path;
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_mark_missing_deleted(path, admobj->adm, temp_pool));
-
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *remove_from_revision_control(PyObject *self, PyObject *args)
-{
-       char *name;
-       svn_boolean_t destroy_wf = FALSE, instant_error = FALSE;
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-
-       if (!PyArg_ParseTuple(args, "s|bb", &name, &destroy_wf, &instant_error))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool,
-               svn_wc_remove_from_revision_control(admobj->adm, name,
-                       destroy_wf, instant_error, py_cancel_check, NULL, temp_pool));
-
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-#if ONLY_SINCE_SVN(1, 6)
-static svn_error_t *wc_validator3(void *baton, const char *uuid, const char *url, const char *root_url, apr_pool_t *pool)
-{
-       PyObject *py_validator = baton, *ret;
-
-       if (py_validator == Py_None) {
-               return NULL;
-       }
-
-       ret = PyObject_CallFunction(py_validator, "sss", uuid, url, root_url);
-       if (ret == NULL) {
-               return py_svn_error();
-       }
-
-       Py_DECREF(ret);
-
-       return NULL;
-}
-
-#else
-
-static svn_error_t *wc_validator2(void *baton, const char *uuid, const char *url, svn_boolean_t root, apr_pool_t *pool)
-{
-       PyObject *py_validator = baton, *ret;
-
-       if (py_validator == Py_None) {
-               return NULL;
-       }
-
-       ret = PyObject_CallFunction(py_validator, "ssO", uuid, url, Py_None);
-       if (ret == NULL) {
-               return py_svn_error();
-       }
-
-       Py_DECREF(ret);
-
-       return NULL;
-}
-
-#endif
-
-static PyObject *relocate(PyObject *self, PyObject *args)
-{
-       char *path, *from, *to;
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-       svn_boolean_t recurse = TRUE;
-       PyObject *py_validator = Py_None;
-
-       if (!PyArg_ParseTuple(args, "sss|bO:relocate", &path, &from, &to, &recurse,
-                       &py_validator))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-#if ONLY_SINCE_SVN(1, 6)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_relocate3(path, admobj->adm, from, to, recurse, wc_validator3, py_validator, temp_pool));
-#else
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_relocate2(path, admobj->adm, from, to, recurse, wc_validator2, py_validator, temp_pool));
-#endif
-
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *crop_tree(PyObject *self, PyObject *args)
-{
-       char *target;
-       svn_depth_t depth;
-       PyObject *notify;
-       apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-
-       if (!PyArg_ParseTuple(args, "si|O", &target, &depth, &notify))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-#if ONLY_SINCE_SVN(1, 6)
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_crop_tree(admobj->adm,
-               target, depth, py_wc_notify_func, notify,
-               py_cancel_check, NULL, temp_pool));
-
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-#else
-       PyErr_SetString(PyExc_NotImplementedError,
-                                       "crop_tree only available on subversion < 1.6");
-       return NULL;
-#endif
-}
-
-static PyObject *translated_stream(PyObject *self, PyObject *args)
-{
-       char *path, *versioned_file;
-       StreamObject *ret;
-       svn_stream_t *stream;
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *stream_pool;
-       int flags;
-
-       if (!PyArg_ParseTuple(args, "ssi", &path, &versioned_file, &flags))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-#if ONLY_SINCE_SVN(1, 5)
-       stream_pool = Pool(NULL);
-       if (stream_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(stream_pool,
-               svn_wc_translated_stream(&stream, path, versioned_file, admobj->adm,
-                       flags, stream_pool));
-
-       ret = PyObject_New(StreamObject, &Stream_Type);
-       if (ret == NULL)
-               return NULL;
-
-       ret->pool = stream_pool;
-       ret->closed = FALSE;
-       ret->stream = stream;
-
-       return (PyObject *)ret;
-#else
-       PyErr_SetString(PyExc_NotImplementedError,
-               "translated_stream() is only available on Subversion >= 1.5");
-       return NULL;
-#endif
-}
-
-static PyObject *adm_text_modified(PyObject *self, PyObject *args)
-{
-       char *path;
-       svn_boolean_t force_comparison = FALSE;
-       apr_pool_t *temp_pool;
-       svn_boolean_t ret;
-       AdmObject *admobj = (AdmObject *)self;
-
-       if (!PyArg_ParseTuple(args, "s|b", &path, &force_comparison))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool,
-                 svn_wc_text_modified_p(&ret, path, force_comparison, admobj->adm,
-                       temp_pool));
-
-       apr_pool_destroy(temp_pool);
-
-       return PyBool_FromLong(ret);
-}
-
-static PyObject *adm_props_modified(PyObject *self, PyObject *args)
-{
-       char *path;
-       apr_pool_t *temp_pool;
-       svn_boolean_t ret;
-       AdmObject *admobj = (AdmObject *)self;
-
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool,
-                 svn_wc_props_modified_p(&ret, path, admobj->adm, temp_pool));
-
-       apr_pool_destroy(temp_pool);
-
-       return PyBool_FromLong(ret);
-}
-
-static PyObject *adm_process_committed_queue(PyObject *self, PyObject *args)
-{
-       apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-       svn_revnum_t revnum;
-       char *date, *author;
-       CommittedQueueObject *py_queue;
-
-       if (!PyArg_ParseTuple(args, "O!lss", &CommittedQueue_Type, &py_queue,
-                       &revnum, &date, &author))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-#if ONLY_SINCE_SVN(1, 5)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_process_committed_queue(py_queue->queue, admobj->adm, revnum, date, author, temp_pool));
-#else
-       {
-               int i;
-               for (i = 0; i < py_queue->queue->queue->nelts; i++) {
-                       committed_queue_item_t *cqi = APR_ARRAY_IDX(py_queue->queue->queue, i,
-                                                                                                               committed_queue_item_t *);
-
-                       RUN_SVN_WITH_POOL(temp_pool, svn_wc_process_committed3(cqi->path, admobj->adm,
-                                  cqi->recurse, revnum, date, author, cqi->wcprop_changes,
-                                  cqi->remove_lock, cqi->digest, temp_pool));
-               }
-       }
-#endif
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *get_actual_target(PyObject *self, PyObject *args)
-{
-       char *path;
-       const char *anchor = NULL, *target = NULL;
-       apr_pool_t *temp_pool;
-       PyObject *ret;
-
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool,
-                 svn_wc_get_actual_target(svn_dirent_canonicalize(path, temp_pool),
-                                                                  &anchor, &target, temp_pool));
-
-       ret = Py_BuildValue("(ss)", anchor, target);
-
-       apr_pool_destroy(temp_pool);
-
-       return ret;
-}
-
-static PyObject *is_wc_root(PyObject *self, PyObject *args)
-{
-       char *path;
-       svn_boolean_t wc_root;
-       apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(temp_pool,
-                 svn_wc_is_wc_root(&wc_root, path, admobj->adm, temp_pool));
-
-       apr_pool_destroy(temp_pool);
-
-       return PyBool_FromLong(wc_root);
-}
-
-static PyObject *transmit_text_deltas(PyObject *self, PyObject *args)
-{
-       char *path;
-       const char *tempfile;
-       svn_boolean_t fulltext;
-       PyObject *editor_obj, *py_digest;
-       unsigned char digest[APR_MD5_DIGESTSIZE];
-       apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-       PyObject *ret;
-
-       if (!PyArg_ParseTuple(args, "sbO", &path, &fulltext, &editor_obj))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       Py_INCREF(editor_obj);
-
-       RUN_SVN_WITH_POOL(temp_pool,
-               svn_wc_transmit_text_deltas2(&tempfile, digest,
-                       svn_dirent_canonicalize(path, temp_pool), admobj->adm, fulltext,
-                       &py_editor, editor_obj, temp_pool));
-
-       py_digest = PyBytes_FromStringAndSize((char *)digest, APR_MD5_DIGESTSIZE);
-       if (py_digest == NULL) {
-               apr_pool_destroy(temp_pool);
-               return NULL;
-       }
-
-       ret = Py_BuildValue("sN", tempfile, py_digest);
-       if (ret == NULL) {
-               apr_pool_destroy(temp_pool);
-               return NULL;
-       }
-
-       apr_pool_destroy(temp_pool);
-
-       return ret;
-}
-
-static PyObject *transmit_prop_deltas(PyObject *self, PyObject *args)
-{
-       char *path;
-       PyObject *editor_obj;
-       apr_pool_t *temp_pool;
-       AdmObject *admobj = (AdmObject *)self;
-       EntryObject *py_entry;
-
-       if (!PyArg_ParseTuple(args, "sO!O", &path, &Entry_Type, &py_entry, &editor_obj))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-
-       Py_INCREF(editor_obj);
-
-       RUN_SVN_WITH_POOL(temp_pool,
-               svn_wc_transmit_prop_deltas(svn_dirent_canonicalize(path, temp_pool),
-                       admobj->adm, &(py_entry->entry), &py_editor, editor_obj, NULL, temp_pool));
-
-       apr_pool_destroy(temp_pool);
-
-       Py_RETURN_NONE;
-}
-
-static PyObject *retrieve(PyObject *self, PyObject *args)
-{
-       char *path;
-       svn_wc_adm_access_t *result;
-       AdmObject *admobj = (AdmObject *)self, *ret;
-       apr_pool_t *pool;
-
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       pool = Pool(NULL);
-       if (pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(pool, svn_wc_adm_retrieve(&result, admobj->adm,
-               svn_dirent_canonicalize(path, pool), pool));
-
-       ret = PyObject_New(AdmObject, &Adm_Type);
-       if (ret == NULL)
-               return NULL;
-
-       ret->pool = pool;
-       ret->adm = result;
-
-       return (PyObject *)ret;
-}
-
-static PyObject *probe_retrieve(PyObject *self, PyObject *args)
-{
-       char *path;
-       svn_wc_adm_access_t *result;
-       AdmObject *admobj = (AdmObject *)self, *ret;
-       apr_pool_t *pool;
-
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       pool = Pool(NULL);
-       if (pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(pool, svn_wc_adm_probe_retrieve(&result, admobj->adm,
-               svn_dirent_canonicalize(path, pool), pool));
-
-       ret = PyObject_New(AdmObject, &Adm_Type);
-       if (ret == NULL)
-               return NULL;
-
-       ret->pool = pool;
-       ret->adm = result;
-
-       return (PyObject *)ret;
-}
-
-static PyObject *probe_try(PyObject *self, PyObject *args)
-{
-       char *path;
-       svn_wc_adm_access_t *result = NULL;
-       AdmObject *admobj = (AdmObject *)self, *ret;
+       const char *path;
        apr_pool_t *pool;
-       int levels_to_lock = -1;
-       svn_boolean_t writelock = FALSE;
-
-       if (!PyArg_ParseTuple(args, "s|bi", &path, &writelock, &levels_to_lock))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       pool = Pool(NULL);
-       if (pool == NULL)
-               return NULL;
-
-       RUN_SVN_WITH_POOL(pool, svn_wc_adm_probe_try3(&result, admobj->adm,
-               svn_dirent_canonicalize(path, pool), writelock, levels_to_lock,
-               py_cancel_check, NULL, pool));
-
-       if (result == NULL) {
-               apr_pool_destroy(pool);
-               Py_RETURN_NONE;
-       }
-
-       ret = PyObject_New(AdmObject, &Adm_Type);
-       if (ret == NULL)
-               return NULL;
-
-       ret->pool = pool;
-       ret->adm = result;
-
-       return (PyObject *)ret;
-}
-
-static PyObject *resolved_conflict(PyObject *self, PyObject *args)
-{
-       AdmObject *admobj = (AdmObject *)self;
-       apr_pool_t *temp_pool;
-       svn_boolean_t resolve_props, resolve_tree, resolve_text;
-       int depth;
-#if ONLY_SINCE_SVN(1, 5)
-       svn_wc_conflict_choice_t conflict_choice;
-#else
-       int conflict_choice;
-#endif
-       PyObject *notify_func = Py_None;
-       char *path;
-
-       if (!PyArg_ParseTuple(args, "sbbbii|O", &path, &resolve_text,
-                                                 &resolve_props, &resolve_tree, &depth,
-                                                 &conflict_choice, &notify_func))
-               return NULL;
-
-       ADM_CHECK_CLOSED(admobj);
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
+       int wc_format;
+       PyObject *py_path;
 
-#if ONLY_SINCE_SVN(1, 6)
-       RUN_SVN_WITH_POOL(temp_pool,
-                 svn_wc_resolved_conflict4(path, admobj->adm, resolve_text,
-                                                                               resolve_props, resolve_tree, depth,
-                                                                               conflict_choice, py_wc_notify_func,
-                                                                          (void *)notify_func, py_cancel_check,
-                                                                          NULL, temp_pool));
-#elif ONLY_SINCE_SVN(1, 5)
-       if (resolve_tree) {
-               PyErr_SetString(PyExc_NotImplementedError,
-                                               "resolve_tree not supported with svn < 1.6");
-               apr_pool_destroy(temp_pool);
-               return NULL;
-       } else {
-               RUN_SVN_WITH_POOL(temp_pool,
-                         svn_wc_resolved_conflict3(path, admobj->adm, resolve_text,
-                                                                                       resolve_props, depth,
-                                                                                       conflict_choice, py_wc_notify_func,
-                                                                                  (void *)notify_func, py_cancel_check,
-                                                                                  NULL, temp_pool));
-       }
-#else
-       if (resolve_tree) {
-               PyErr_SetString(PyExc_NotImplementedError,
-                                               "resolve_tree not supported with svn < 1.6");
-               apr_pool_destroy(temp_pool);
-               return NULL;
-       } else if (depth != svn_depth_infinity && depth != svn_depth_files) {
-               PyErr_SetString(PyExc_NotImplementedError,
-                                               "only infinity and files values for depth are supported");
-               apr_pool_destroy(temp_pool);
+       if (!PyArg_ParseTuple(args, "O", &py_path))
                return NULL;
-       } else if (conflict_choice != 0) {
-               PyErr_SetString(PyExc_NotImplementedError,
-                                               "conflict choice not supported with svn < 1.5");
-               apr_pool_destroy(temp_pool);
+
+       pool = Pool(NULL);
+       if (pool == NULL) {
                return NULL;
-       } else {
-               RUN_SVN_WITH_POOL(temp_pool,
-                         svn_wc_resolved_conflict2(path, admobj->adm, resolve_text,
-                                                                                       resolve_props,
-                                                                                       (depth == svn_depth_infinity),
-                                                                                       py_wc_notify_func,
-                                                                                  (void *)notify_func, py_cancel_check,
-                                                                                  NULL,
-                                                                                  temp_pool));
        }
-#endif
 
-       apr_pool_destroy(temp_pool);
+       path = py_object_to_svn_dirent(py_path, pool);
+       if (path == NULL) {
+               apr_pool_destroy(pool);
+               return NULL;
+       }
 
-       Py_RETURN_NONE;
+       RUN_SVN_WITH_POOL(pool, svn_wc_check_wc(path, &wc_format, pool));
+       apr_pool_destroy(pool);
+       return PyLong_FromLong(wc_format);
 }
 
-static PyObject *conflicted(PyObject *self, PyObject *args)
+static PyObject *cleanup_wc(PyObject *self, PyObject *args, PyObject *kwargs)
 {
-       char *path;
+       const char *path;
+       char *diff3_cmd = NULL;
+       char *kwnames[] = { "path", "diff3_cmd", NULL };
        apr_pool_t *temp_pool;
-       PyObject *ret;
-       AdmObject *admobj = (AdmObject *)self;
-       svn_boolean_t text_conflicted, prop_conflicted, tree_conflicted;
+       PyObject *py_path;
 
-       if (!PyArg_ParseTuple(args, "s", &path))
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|z", kwnames,
+                                                                        &py_path, &diff3_cmd))
                return NULL;
 
-       ADM_CHECK_CLOSED(admobj);
-
        temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
+       if (temp_pool == NULL) {
                return NULL;
+       }
 
-#if ONLY_SINCE_SVN(1, 6)
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_conflicted_p2(&text_conflicted,
-               &prop_conflicted, &tree_conflicted, path, admobj->adm, temp_pool));
-
-       ret = Py_BuildValue("(bbb)", text_conflicted, prop_conflicted, tree_conflicted);
-#else
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_conflicted_p(&text_conflicted,
-               &prop_conflicted, path, admobj->adm, temp_pool));
+       path = py_object_to_svn_dirent(py_path, temp_pool);
+       if (path == NULL) {
+               apr_pool_destroy(temp_pool);
+               return NULL;
+       }
 
-       ret = Py_BuildValue("(bbO)", text_conflicted, prop_conflicted, Py_None);
-#endif
+       RUN_SVN_WITH_POOL(temp_pool,
+                               svn_wc_cleanup2(path, diff3_cmd, py_cancel_check, NULL,
+                                                               temp_pool));
 
        apr_pool_destroy(temp_pool);
 
-       return ret;
+       Py_RETURN_NONE;
 }
 
-/**
- * Determine the status of a file in the specified working copy.
- *
- * :return: A status object.
- */
-static PyObject *ra_status(PyObject *self, PyObject *args)
+static PyObject *match_ignore_list(PyObject *self, PyObject *args)
 {
-       char *path;
-       svn_wc_status2_t *st;
+#if ONLY_SINCE_SVN(1, 5)
+       char *str;
+       PyObject *py_list;
+       apr_array_header_t *list;
        apr_pool_t *temp_pool;
-       PyObject *ret;
-       AdmObject *admobj = (AdmObject *)self;
+       svn_boolean_t ret;
 
-       if (!PyArg_ParseTuple(args, "s", &path))
+       if (!PyArg_ParseTuple(args, "sO", &str, &py_list))
                return NULL;
 
-       ADM_CHECK_CLOSED(admobj);
-
        temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
 
-       RUN_SVN_WITH_POOL(temp_pool,
-                       svn_wc_status2(
-                               &st,
-                               svn_dirent_canonicalize(svn_dirent_join(svn_wc_adm_access_path(admobj->adm), path, temp_pool), temp_pool),
-                               admobj->adm,
-                               temp_pool));
+       if (!string_list_to_apr_array(temp_pool, py_list, &list)) {
+               apr_pool_destroy(temp_pool);
+               return NULL;
+       }
 
-       ret = py_status(st);
+       ret = svn_wc_match_ignore_list(str, list, temp_pool);
 
        apr_pool_destroy(temp_pool);
 
-       return (PyObject*)ret;
-}
-
-static PyMethodDef adm_methods[] = {
-       { "prop_set", adm_prop_set, METH_VARARGS, "S.prop_set(name, value, path, skip_checks=False)" },
-       { "access_path", (PyCFunction)adm_access_path, METH_NOARGS,
-               "S.access_path() -> path\n"
-               "Returns the base path for this working copy handle." },
-       { "prop_get", adm_prop_get, METH_VARARGS, "S.prop_get(name, path) -> value" },
-       { "entries_read", adm_entries_read, METH_VARARGS, "S.entries_read(include_hidden=False) -> dict" },
-       { "walk_entries", adm_walk_entries, METH_VARARGS,
-               "S.walk_entries(path, callback, show_hidden=False)\n"
-               "callback should be a function that takes a path and a wc entry" },
-       { "locked", (PyCFunction)adm_locked, METH_NOARGS,
-               "S.locked() -> bool" },
-       { "get_prop_diffs", adm_get_prop_diffs, METH_VARARGS,
-               "S.get_prop_diffs(path) -> (propchanges, originalprops)" },
-       { "add", (PyCFunction)adm_add, METH_VARARGS|METH_KEYWORDS, "S.add(path, copyfrom_url=None, copyfrom_rev=-1, notify_func=None)" },
-       { "copy", adm_copy, METH_VARARGS, "S.copy(src_path, dest_path, notify_func=None)" },
-       { "delete", (PyCFunction)adm_delete, METH_VARARGS|METH_KEYWORDS, "S.delete(path, notify_func=None, keep_local=False)" },
-       { "crawl_revisions", (PyCFunction)adm_crawl_revisions, METH_VARARGS|METH_KEYWORDS,
-               "S.crawl_revisions(path, reporter, restore_files=True, recurse=True, use_commit_times=True, notify_func=None) -> None" },
-       { "get_update_editor", adm_get_update_editor, METH_VARARGS, NULL },
-       { "close", (PyCFunction)adm_close, METH_NOARGS,
-               "S.close()" },
-       { "entry", (PyCFunction)adm_entry, METH_VARARGS,
-               "s.entry(path, show_hidden=False) -> entry" },
-       { "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)" },
-       { "process_committed_queue", (PyCFunction)adm_process_committed_queue, METH_VARARGS, "S.process_committed_queue(queue, new_revnum, rev_date, rev_author)" },
-       { "remove_lock", (PyCFunction)adm_remove_lock, METH_VARARGS, "S.remove_lock(path)" },
-       { "has_binary_prop", (PyCFunction)adm_has_binary_prop, METH_VARARGS, "S.has_binary_prop(path) -> bool" },
-       { "text_modified", (PyCFunction)adm_text_modified, METH_VARARGS, "S.text_modified(filename, force_comparison=False) -> bool" },
-       { "props_modified", (PyCFunction)adm_props_modified, METH_VARARGS, "S.props_modified(filename) -> bool" },
-       { "get_ancestry", (PyCFunction)get_ancestry, METH_VARARGS,
-               "S.get_ancestry(path) -> (url, rev)" },
-       { "maybe_set_repos_root", (PyCFunction)maybe_set_repos_root, METH_VARARGS, "S.maybe_set_repos_root(path, repos)" },
-       { "add_repos_file", (PyCFunction)add_repos_file, METH_KEYWORDS,
-               "S.add_repos_file(dst_path, new_base_contents, new_contents, new_base_props, new_props, copyfrom_url=None, copyfrom_rev=-1, notify_func=None)" },
-       { "mark_missing_deleted", (PyCFunction)mark_missing_deleted, METH_VARARGS,
-               "S.mark_missing_deleted(path)" },
-       { "remove_from_revision_control", (PyCFunction)remove_from_revision_control, METH_VARARGS,
-               "S.remove_from_revision_control(name, destroy_wf=False, instant_error=False)" },
-       { "relocate", (PyCFunction)relocate, METH_VARARGS,
-               "S.relocate(path, from, to, recurse=TRUE, validator=None)" },
-       { "crop_tree", (PyCFunction)crop_tree, METH_VARARGS,
-               "S.crop_tree(target, depth, notify_func=None, cancel=None)" },
-       { "translated_stream", (PyCFunction)translated_stream, METH_VARARGS,
-               "S.translated_stream(path, versioned_file, flags) -> stream" },
-       { "is_wc_root", (PyCFunction)is_wc_root, METH_VARARGS,
-               "S.is_wc_root(path) -> wc_root" },
-       { "transmit_text_deltas", (PyCFunction)transmit_text_deltas, METH_VARARGS,
-               "S.transmit_text_deltas(fulltext, editor) -> (tempfile, digest)" },
-       { "transmit_prop_deltas", (PyCFunction)transmit_prop_deltas, METH_VARARGS,
-               "S.transmit_prop_deltas(path, entry, editor)" },
-       { "probe_retrieve", (PyCFunction)probe_retrieve, METH_VARARGS,
-               "S.probe_retrieve(path) -> WorkingCopy" },
-       { "retrieve", (PyCFunction)retrieve, METH_VARARGS,
-               "S.retrieve(path) -> WorkingCopy" },
-       { "probe_try", (PyCFunction)probe_try, METH_VARARGS,
-               "S.probe_try(path, write_lock=False, levels_to_lock=-1)" },
-       { "conflicted", (PyCFunction)conflicted, METH_VARARGS,
-               "S.conflicted(path) -> (text_conflicted, prop_conflicted, tree_conflicted)" },
-       { "resolved_conflict", (PyCFunction)resolved_conflict, METH_VARARGS,
-               "S.resolved_conflict(path, resolve_text, resolve_props, resolve_tree, depth, conflict_choice, notify_func=None, cancel=None)" },
-       { "status", (PyCFunction)ra_status, METH_VARARGS, "status(wc_path) -> Status" },
-       { NULL, }
-};
-
-static PyTypeObject Adm_Type = {
-       PyVarObject_HEAD_INIT(NULL, 0)
-       "wc.WorkingCopy", /*    const char *tp_name;  For printing, in format "<module>.<name>" */
-       sizeof(AdmObject),
-       0,/*    Py_ssize_t tp_basicsize, tp_itemsize;  For allocation */
-
-       /* Methods to implement standard operations */
-
-       adm_dealloc, /* destructor tp_dealloc;  */
-       NULL, /*        printfunc tp_print;     */
-       NULL, /*        getattrfunc tp_getattr; */
-       NULL, /*        setattrfunc tp_setattr; */
-       NULL, /*        cmpfunc tp_compare;     */
-       adm_repr, /*    reprfunc tp_repr;       */
-
-       /* Method suites for standard classes */
-
-       NULL, /*        PyNumberMethods *tp_as_number;  */
-       NULL, /*        PySequenceMethods *tp_as_sequence;      */
-       NULL, /*        PyMappingMethods *tp_as_mapping;        */
-
-       /* More standard operations (here for binary compatibility) */
-
-       NULL, /*        hashfunc tp_hash;       */
-       NULL, /*        ternaryfunc tp_call;    */
-       adm_repr, /*    reprfunc tp_repr;       */
-       NULL, /*        getattrofunc tp_getattro;       */
-       NULL, /*        setattrofunc tp_setattro;       */
-
-       /* Functions to access object as input/output buffer */
-       NULL, /*        PyBufferProcs *tp_as_buffer;    */
-
-       /* Flags to define presence of optional/expanded features */
-       0, /*   long tp_flags;  */
-
-       "Local working copy", /*        const char *tp_doc;  Documentation string */
-
-       /* Assigned meaning in release 2.0 */
-       /* call function for all accessible objects */
-       NULL, /*        traverseproc tp_traverse;       */
-
-       /* delete references to contained objects */
-       NULL, /*        inquiry tp_clear;       */
-
-       /* Assigned meaning in release 2.1 */
-       /* rich comparisons */
-       NULL, /*        richcmpfunc tp_richcompare;     */
-
-       /* weak reference enabler */
-       0, /*   Py_ssize_t tp_weaklistoffset;   */
-
-       /* Added in release 2.2 */
-       /* Iterators */
-       NULL, /*        getiterfunc tp_iter;    */
-       NULL, /*        iternextfunc tp_iternext;       */
+       return PyBool_FromLong(ret);
+#else
+       PyErr_SetNone(PyExc_NotImplementedError);
+       return NULL;
+#endif
+}
 
-       /* Attribute descriptor and subclassing stuff */
-       adm_methods, /* struct PyMethodDef *tp_methods; */
-       NULL, /*        struct PyMemberDef *tp_members; */
-       NULL, /*        struct PyGetSetDef *tp_getset;  */
-       NULL, /*        struct _typeobject *tp_base;    */
-       NULL, /*        PyObject *tp_dict;      */
-       NULL, /*        descrgetfunc tp_descr_get;      */
-       NULL, /*        descrsetfunc tp_descr_set;      */
-       0, /*   Py_ssize_t tp_dictoffset;       */
-       NULL, /*        initproc tp_init;       */
-       NULL, /*        allocfunc tp_alloc;     */
-       adm_init, /*    newfunc tp_new; */
+static PyMethodDef wc_methods[] = {
+    { "check_wc", check_wc, METH_VARARGS, "check_wc(path) -> version\n"
+        "Check whether path contains a Subversion working copy\n"
+            "return the workdir version"},
+    { "cleanup", (PyCFunction)cleanup_wc,
+        METH_VARARGS|METH_KEYWORDS, "cleanup(path, diff3_cmd=None)\n" },
+    { "ensure_adm", (PyCFunction)ensure_adm, METH_KEYWORDS|METH_VARARGS,
+        "ensure_adm(path, uuid, url, repos=None, rev=None)" },
+    { "get_adm_dir", (PyCFunction)get_adm_dir, METH_NOARGS,
+        "get_adm_dir() -> name" },
+    { "set_adm_dir", (PyCFunction)set_adm_dir, METH_VARARGS,
+        "set_adm_dir(name)" },
+    { "get_pristine_copy_path", get_pristine_copy_path, METH_VARARGS,
+        "get_pristine_copy_path(path) -> path" },
+    { "get_pristine_contents", get_pristine_contents, METH_VARARGS,
+        "get_pristine_contents(path) -> stream" },
+    { "is_adm_dir", is_adm_dir, METH_VARARGS,
+        "is_adm_dir(name) -> bool" },
+    { "is_normal_prop", is_normal_prop, METH_VARARGS,
+        "is_normal_prop(name) -> bool" },
+    { "is_entry_prop", is_entry_prop, METH_VARARGS,
+        "is_entry_prop(name) -> bool" },
+    { "is_wc_prop", is_wc_prop, METH_VARARGS,
+        "is_wc_prop(name) -> bool" },
+    { "revision_status", (PyCFunction)revision_status,
+        METH_KEYWORDS|METH_VARARGS,
+        "revision_status(wc_path, trail_url=None, committed=False)"
+            "-> (min_rev, max_rev, switched, modified)" },
+    { "version", (PyCFunction)version, METH_NOARGS,
+        "version() -> (major, minor, patch, tag)\n\n"
+            "Version of libsvn_wc currently used."
+    },
+    { "api_version", (PyCFunction)api_version, METH_NOARGS,
+        "api_version() -> (major, minor, patch, tag)\n\n"
+            "Version of libsvn_wc Subvertpy was compiled against." },
+    { "match_ignore_list", (PyCFunction)match_ignore_list, METH_VARARGS,
+        "match_ignore_list(str, patterns) -> bool" },
+    { "get_actual_target", (PyCFunction)get_actual_target, METH_VARARGS,
+        "get_actual_target(path) -> (anchor, target)" },
+    { NULL, }
 };
 
 static void committed_queue_dealloc(PyObject *self)
@@ -2212,68 +880,118 @@ static PyObject *committed_queue_init(PyTypeObject *self, PyObject *args, PyObje
        return (PyObject *)ret;
 }
 
-static PyObject *committed_queue_queue(CommittedQueueObject *self, PyObject *args)
+static PyObject *committed_queue_queue(CommittedQueueObject *self, PyObject *args, PyObject *kwargs)
 {
-       char *path;
-       AdmObject *admobj;
-       PyObject *py_wcprop_changes = Py_None;
-       svn_boolean_t remove_lock = FALSE, remove_changelist = FALSE;
-       char *digest = NULL;
-       svn_boolean_t recurse = FALSE;
-       apr_pool_t *temp_pool;
+       const char *path;
+       PyObject *admobj;
+       PyObject *py_wcprop_changes = Py_None, *py_path;
+    svn_wc_adm_access_t *adm = NULL;
+       bool remove_lock = false, remove_changelist = false;
+       char *md5_digest = NULL, *sha1_digest = NULL;
+       bool recurse = false;
        apr_array_header_t *wcprop_changes;
-       int digest_len;
+       int md5_digest_len, sha1_digest_len;
+#if ONLY_SINCE_SVN(1, 7)
+       svn_wc_context_t *context = NULL;
+#endif
+       char *kwnames[] = { "path", "adm", "recurse", "wcprop_changes", "remove_lock", "remove_changelist", "md5_digest", "sha1_digest", NULL };
 
-       if (!PyArg_ParseTuple(args, "sO!|bObbz#", &path, &Adm_Type, &admobj,
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|bObbz#z#", kwnames,
+                                                                        &py_path, &admobj,
                                                  &recurse, &py_wcprop_changes, &remove_lock,
-                                                 &remove_changelist, &digest, &digest_len))
-               return NULL;
-
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
+                                                 &remove_changelist, &md5_digest, &md5_digest_len,
+                                                 &sha1_digest, &sha1_digest_len))
                return NULL;
 
        if (!py_dict_to_wcprop_changes(py_wcprop_changes, self->pool, &wcprop_changes)) {
-               apr_pool_destroy(temp_pool);
                return NULL;
        }
 
-       path = apr_pstrdup(self->pool, path);
+       path = py_object_to_svn_abspath(py_path, self->pool);
        if (path == NULL) {
-               PyErr_NoMemory();
                return NULL;
        }
 
-       if (digest != NULL) {
-               if (digest_len != APR_MD5_DIGESTSIZE) {
+       if (md5_digest != NULL) {
+               if (md5_digest_len != APR_MD5_DIGESTSIZE) {
                        PyErr_SetString(PyExc_ValueError, "Invalid size for md5 digest");
-                       apr_pool_destroy(temp_pool);
                        return NULL;
                }
-               digest = apr_pstrdup(self->pool, digest);
-               if (digest == NULL) {
-                       PyErr_NoMemory();
+       }
+
+       if (sha1_digest != NULL) {
+               if (sha1_digest_len != APR_SHA1_DIGESTSIZE) {
+                       PyErr_SetString(PyExc_ValueError, "Invalid size for sha1 digest");
                        return NULL;
                }
        }
 
-       RUN_SVN_WITH_POOL(temp_pool,
-               svn_wc_queue_committed(&self->queue, path, admobj->adm, recurse,
-                                                          wcprop_changes, remove_lock, remove_changelist,
-                                                          (unsigned char *)digest, temp_pool));
+       if (PyObject_IsInstance(admobj, (PyObject *)&Adm_Type)) {
+               adm = PyObject_GetAdmAccess(admobj);
+#if ONLY_SINCE_SVN(1, 7)
+       } else if (PyObject_IsInstance(admobj, (PyObject *)&Context_Type)) {
+               context = ((ContextObject*)admobj)->context;
+#endif
+       } else {
+               PyErr_SetString(PyExc_TypeError, "Second arguments needs to be Adm or Context");
+               return NULL;
+       }
 
-       apr_pool_destroy(temp_pool);
+#if ONLY_SINCE_SVN(1, 7)
+       if (adm != NULL) {
+#endif
+#if ONLY_SINCE_SVN(1, 6)
+       {
+       svn_checksum_t *svn_checksum_p;
+
+       if (md5_digest != NULL) {
+               svn_checksum_p  = apr_palloc(self->pool, sizeof(svn_checksum_t));
+        svn_checksum_p->digest = apr_pmemdup(
+            self->pool, (unsigned char *)md5_digest, APR_MD5_DIGESTSIZE);
+               svn_checksum_p->kind = svn_checksum_md5;
+       } else {
+               svn_checksum_p = NULL;
+       }
+       RUN_SVN(
+               svn_wc_queue_committed2(self->queue, path, adm, recurse?TRUE:FALSE,
+                                                          wcprop_changes, remove_lock?TRUE:FALSE, remove_changelist?TRUE:FALSE,
+                                                          svn_checksum_p, self->pool));
+       }
+#else
+       RUN_SVN(
+               svn_wc_queue_committed(&self->queue, path, adm, recurse?TRUE:FALSE,
+                                                          wcprop_changes, remove_lock?TRUE:FALSE, remove_changelist?TRUE:FALSE,
+                                                          (unsigned char *)md5_digest, self->pool));
+#endif
+#if ONLY_SINCE_SVN(1, 7)
+       } else {
+               svn_checksum_t *svn_checksum_p;
+
+               if (sha1_digest != NULL) {
+                       svn_checksum_p  = apr_palloc(self->pool, sizeof(svn_checksum_t));
+                       svn_checksum_p->digest = apr_pmemdup(
+                               self->pool, (unsigned char *)sha1_digest, APR_SHA1_DIGESTSIZE);
+                       svn_checksum_p->kind = svn_checksum_sha1;
+               } else {
+                       svn_checksum_p = NULL;
+               }
+               RUN_SVN(
+                       svn_wc_queue_committed3(self->queue, context, path, recurse?TRUE:FALSE,
+                                                                  wcprop_changes, remove_lock?TRUE:FALSE, remove_changelist?TRUE:FALSE,
+                                                                  svn_checksum_p, self->pool));
+       }
+#endif
 
        Py_RETURN_NONE;
 }
 
 static PyMethodDef committed_queue_methods[] = {
-       { "queue", (PyCFunction)committed_queue_queue, METH_VARARGS,
-               "S.queue(path, adm, recurse, wcprop_changes, remove_lock, remove_changelist, digest)" },
+       { "queue", (PyCFunction)committed_queue_queue, METH_VARARGS|METH_KEYWORDS,
+               "S.queue(path, adm, recurse=False, wcprop_changes=[], remove_lock=False, remove_changelist=False, digest=None)" },
        { NULL }
 };
 
-static PyTypeObject CommittedQueue_Type = {
+PyTypeObject CommittedQueue_Type = {
        PyVarObject_HEAD_INIT(NULL, 0)
        "wc.CommittedQueue", /* const char *tp_name;  For printing, in format "<module>.<name>" */
        sizeof(CommittedQueueObject),
@@ -2343,352 +1061,1062 @@ static PyTypeObject CommittedQueue_Type = {
        committed_queue_init, /*        newfunc tp_new; */
 };
 
-/**
- * Determine the revision status of a specified working copy.
- *
- * :return: Tuple with minimum and maximum revnums found, whether the
- * working copy was switched and whether it was modified.
- */
-static PyObject *revision_status(PyObject *self, PyObject *args, PyObject *kwargs)
+svn_lock_t *py_object_to_svn_lock(PyObject *py_lock, apr_pool_t *pool)
 {
-       char *kwnames[] = { "wc_path", "trail_url", "committed",  NULL };
-       char *wc_path, *trail_url=NULL;
-       bool committed=false;
-       PyObject *ret;
-        svn_wc_revision_status_t *revstatus;
-       apr_pool_t *temp_pool;
+       LockObject* lockobj = (LockObject *)py_lock;
+    if (!PyObject_IsInstance(py_lock, (PyObject *)&Lock_Type)) {
+        PyErr_SetString(PyExc_TypeError, "Expected Lock object");
+        return NULL;
+    }
+       return &lockobj->lock;
+}
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zb", kwnames, &wc_path,
-                                                                        &trail_url, &committed))
-               return NULL;
+#if ONLY_SINCE_SVN(1, 7)
+static PyTypeObject Context_Type;
 
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-       RUN_SVN_WITH_POOL(temp_pool,
-                       svn_wc_revision_status(
-                               &revstatus,
-                               svn_dirent_canonicalize(wc_path, temp_pool),
-                               trail_url,
-                                committed, py_cancel_check, NULL, temp_pool));
-       ret = Py_BuildValue("(llbb)", revstatus->min_rev, revstatus->max_rev,
-                       revstatus->switched, revstatus->modified);
-       apr_pool_destroy(temp_pool);
-       return ret;
+static PyObject *py_wc_context_locked(PyObject *self, PyObject *args)
+{
+    PyObject* py_path;
+    const char *path;
+    apr_pool_t *pool;
+    svn_wc_context_t *wc_context = ((ContextObject *)self)->context;
+    svn_boolean_t locked_here, locked;
+
+    if (!PyArg_ParseTuple(args, "O", &py_path))
+        return NULL;
+
+    pool = Pool(NULL);
+
+    path = py_object_to_svn_abspath(py_path, pool);
+    if (path == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    RUN_SVN_WITH_POOL(pool, svn_wc_locked2(&locked_here, &locked, wc_context, path, pool));
+
+    apr_pool_destroy(pool);
+
+    return Py_BuildValue("(bb)", locked_here?true:false, locked?true:false);
 }
 
-static PyObject *is_normal_prop(PyObject *self, PyObject *args)
+static PyObject *py_wc_context_check_wc(PyObject *self, PyObject *args)
 {
-       char *name;
+    PyObject* py_path;
+    const char *path;
+    apr_pool_t *pool;
+    svn_wc_context_t *wc_context = ((ContextObject *)self)->context;
+    int wc_format;
 
-       if (!PyArg_ParseTuple(args, "s", &name))
-               return NULL;
+    if (!PyArg_ParseTuple(args, "O", &py_path))
+        return NULL;
 
-       return PyBool_FromLong(svn_wc_is_normal_prop(name));
+    pool = Pool(NULL);
+
+    path = py_object_to_svn_abspath(py_path, pool);
+    if (path == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    RUN_SVN_WITH_POOL(pool, svn_wc_check_wc2(&wc_format, wc_context, path, pool));
+
+    apr_pool_destroy(pool);
+
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(wc_format);
+#else
+    return PyInt_FromLong(wc_format);
+#endif
 }
 
-static PyObject *is_adm_dir(PyObject *self, PyObject *args)
+static PyObject *py_wc_context_text_modified_p2(PyObject *self, PyObject *args)
 {
-       char *name;
-       apr_pool_t *pool;
-       svn_boolean_t ret;
+    PyObject* py_path;
+    const char *path;
+    apr_pool_t *pool;
+    svn_wc_context_t *wc_context = ((ContextObject *)self)->context;
+    svn_boolean_t modified;
 
-       if (!PyArg_ParseTuple(args, "s", &name))
-               return NULL;
+    if (!PyArg_ParseTuple(args, "O", &py_path))
+        return NULL;
 
-       pool = Pool(NULL);
-       if (pool == NULL)
-               return NULL;
+    pool = Pool(NULL);
 
-       ret = svn_wc_is_adm_dir(name, pool);
+    path = py_object_to_svn_abspath(py_path, pool);
+    if (path == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
 
-       apr_pool_destroy(pool);
+    RUN_SVN_WITH_POOL(pool, svn_wc_text_modified_p2(&modified, wc_context,
+                                                    path, FALSE, pool));
 
-       return PyBool_FromLong(ret);
+    apr_pool_destroy(pool);
+
+    return PyBool_FromLong(modified);
 }
 
-static PyObject *is_wc_prop(PyObject *self, PyObject *args)
+static PyObject *py_wc_context_props_modified_p2(PyObject *self, PyObject *args)
 {
-       char *name;
+    PyObject* py_path;
+    const char *path;
+    apr_pool_t *pool;
+    svn_wc_context_t *wc_context = ((ContextObject *)self)->context;
+    svn_boolean_t modified;
+
+    if (!PyArg_ParseTuple(args, "O", &py_path))
+        return NULL;
+
+    pool = Pool(NULL);
+
+    path = py_object_to_svn_abspath(py_path, pool);
+    if (path == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    RUN_SVN_WITH_POOL(pool, svn_wc_props_modified_p2(&modified, wc_context,
+                                                    path, pool));
+
+    apr_pool_destroy(pool);
+
+    return PyBool_FromLong(modified);
+}
+
+static PyObject *py_wc_context_conflicted(PyObject *self, PyObject *args)
+{
+    PyObject* py_path;
+    const char *path;
+    apr_pool_t *pool;
+    svn_wc_context_t *wc_context = ((ContextObject *)self)->context;
+    svn_boolean_t text_conflicted, props_conflicted, tree_conflicted;
+
+    if (!PyArg_ParseTuple(args, "O", &py_path))
+        return NULL;
+
+    pool = Pool(NULL);
+
+    path = py_object_to_svn_abspath(py_path, pool);
+    if (path == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    RUN_SVN_WITH_POOL(pool, svn_wc_conflicted_p3(
+         &text_conflicted, &props_conflicted, &tree_conflicted, wc_context,
+         path, pool));
+
+    apr_pool_destroy(pool);
+
+    return Py_BuildValue("(bbb)", text_conflicted, props_conflicted, tree_conflicted);
+}
+
+static PyObject *py_wc_context_crawl_revisions(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject* py_path, *py_reporter;
+    const char *path;
+    apr_pool_t *pool;
+    svn_wc_context_t *wc_context = ((ContextObject *)self)->context;
+    char *kwnames[] = { "path", "reporter", "restore_files", "depth",
+        "honor_depth_exclude", "depth_compatibility_trick", "use_commit_times",
+        "cancel", "notify", NULL };
+    bool restore_files = false;
+    int depth = svn_depth_infinity;
+    bool honor_depth_exclude = true;
+    bool depth_compatibility_trick = false;
+    bool use_commit_times = false;
+    PyObject *notify = Py_None;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|bibbbOO", kwnames,
+                                     &py_path, &py_reporter, &restore_files,
+                                     &depth, &honor_depth_exclude,
+                                     &depth_compatibility_trick,
+                                     &use_commit_times, &notify)) {
+        return NULL;
+    }
+
+    pool = Pool(NULL);
+
+    path = py_object_to_svn_abspath(py_path, pool);
+    if (path == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    RUN_SVN_WITH_POOL(pool, svn_wc_crawl_revisions5(
+         wc_context, path, &py_ra_reporter3, py_reporter, restore_files,
+         depth, honor_depth_exclude, depth_compatibility_trick,
+         use_commit_times, py_cancel_check, NULL, py_wc_notify_func, notify, pool));
+
+    apr_pool_destroy(pool);
+
+    Py_RETURN_NONE;
+}
+
+static void context_done_handler(void *self)
+{
+    PyObject *selfobj = (PyObject *)self;
+
+    Py_DECREF(selfobj);
+}
+
+static PyObject *py_wc_context_get_update_editor(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    char *kwnames[] = {
+        "anchor_abspath", "target_basename", "use_commit_times", "depth",
+        "depth_is_sticky", "allow_unver_obstructions", "adds_as_modification",
+        "server_performs_filtering", "clean_checkout", "diff3_cmd",
+        "preserved_exts", "dirents_func", "conflict_func", "external_func",
+        "notify_func", NULL };
+    const svn_delta_editor_t *editor;
+    void *edit_baton;
+    const char *anchor_abspath;
+    char *target_basename;
+    char *diff3_cmd = NULL;
+    svn_wc_context_t *wc_context = ((ContextObject *)self)->context;
+    bool use_commit_times = false;
+    int depth = svn_depth_infinity;
+    bool depth_is_sticky = false;
+    bool allow_unver_obstructions = true;
+    bool adds_as_modification = false;
+    bool server_performs_filtering = false;
+    bool clean_checkout = false;
+    apr_array_header_t *preserved_exts = NULL;
+    PyObject *py_preserved_exts = Py_None;
+    PyObject *dirents_func = Py_None;
+    PyObject *conflict_func = Py_None;
+    PyObject *external_func = Py_None;
+    PyObject *notify_func = Py_None;
+    PyObject *py_anchor_abspath;
+    apr_pool_t *result_pool, *scratch_pool;
+    svn_error_t *err;
+    svn_revnum_t target_revision;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os|bibbbbbzOOOOO", kwnames,
+                                     &py_anchor_abspath, &target_basename,
+                                     &use_commit_times, &depth,
+                                     &depth_is_sticky,
+                                     &allow_unver_obstructions,
+                                     &adds_as_modification,
+                                     &server_performs_filtering,
+                                     &clean_checkout, &py_preserved_exts,
+                                     &dirents_func, &conflict_func,
+                                     &external_func, &notify_func)) {
+        return NULL;
+    }
+
+    if (conflict_func != Py_None) {
+        // TODO
+        PyErr_SetString(PyExc_NotImplementedError,
+                        "conflict_func is not currently supported");
+        return NULL;
+    }
+
+    if (external_func != Py_None) {
+        // TODO
+        PyErr_SetString(PyExc_NotImplementedError,
+                        "external_func is not currently supported");
+        return NULL;
+    }
+
+    if (dirents_func != Py_None) {
+        // TODO
+        PyErr_SetString(PyExc_NotImplementedError,
+                        "dirents_func is not currently supported");
+        return NULL;
+    }
+
+    scratch_pool = Pool(NULL);
+
+    anchor_abspath = py_object_to_svn_abspath(py_anchor_abspath, scratch_pool);
+
+    if (py_preserved_exts != Py_None) {
+        if (!string_list_to_apr_array(scratch_pool, py_preserved_exts, &preserved_exts)) {
+            apr_pool_destroy(scratch_pool);
+            return NULL;
+        }
+    }
+
+    result_pool = Pool(NULL);
+
+    Py_BEGIN_ALLOW_THREADS
+    err = svn_wc_get_update_editor4(
+             &editor, &edit_baton, &target_revision, wc_context,
+             anchor_abspath, target_basename, use_commit_times, depth,
+             depth_is_sticky, allow_unver_obstructions, adds_as_modification,
+             server_performs_filtering, clean_checkout, diff3_cmd,
+             preserved_exts, NULL, dirents_func, NULL, conflict_func, NULL,
+             external_func, py_cancel_check, NULL, py_wc_notify_func,
+             notify_func, result_pool, scratch_pool);
+    Py_END_ALLOW_THREADS
+
+    apr_pool_destroy(scratch_pool);
+
+    if (err != NULL) {
+        handle_svn_error(err);
+        svn_error_clear(err);
+        apr_pool_destroy(result_pool);
+        return NULL;
+    }
+
+    /* TODO: Also return target_revision ? */
+    Py_INCREF(self);
+    return new_editor_object(NULL, editor, edit_baton, result_pool, &Editor_Type,
+                             context_done_handler, self, NULL);
+}
+
+static PyObject *py_wc_context_ensure_adm(PyObject *self, PyObject *args,
+                                          PyObject *kwargs)
+{
+    ContextObject *context_obj = (ContextObject *)self;
+    char *kwnames[] = {
+        "local_abspath", "url", "repos_root_url", "repos_uuid",
+        "revnum", "depth", NULL };
+    char *local_abspath;
+    char *url;
+    char *repos_root_url;
+    char *repos_uuid;
+    int revnum;
+    int depth = svn_depth_infinity;
+    apr_pool_t *pool;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ssssi|i", kwnames,
+                                     &local_abspath, &url, &repos_root_url,
+                                     &repos_uuid, &revnum, &depth)) {
+        return NULL;
+    }
+
+    pool = Pool(NULL);
+
+    RUN_SVN_WITH_POOL(pool, svn_wc_ensure_adm4(context_obj->context,
+                                               local_abspath, url,
+                                               repos_root_url, repos_uuid,
+                                               revnum, depth, pool));
+
+    apr_pool_destroy(pool);
+
+    Py_RETURN_NONE;
+}
+
+typedef struct {
+    PyObject_VAR_HEAD
+    apr_pool_t *pool;
+    svn_wc_status3_t status;
+} Status3Object;
+
+static void status_dealloc(PyObject *self)
+{
+    apr_pool_t *pool = ((Status3Object *)self)->pool;
+    if (pool != NULL)
+        apr_pool_destroy(pool);
+    PyObject_Del(self);
+}
+
+static PyMemberDef status_members[] = {
+    { "kind", T_INT, offsetof(Status3Object, status.kind), READONLY,
+        "The kind of node as recorded in the working copy." },
+    { "depth", T_INT, offsetof(Status3Object, status.depth), READONLY,
+        "The depth of the node as recorded in the working copy." },
+    { "filesize", T_LONG, offsetof(Status3Object, status.filesize), READONLY,
+        "The actual size of the working file on disk, or SVN_INVALID_FILESIZE"
+        "if unknown (or if the item isn't a file at all)" },
+    { "versioned", T_BOOL, offsetof(Status3Object, status.versioned), READONLY,
+        "If the path is under version control, versioned is TRUE, "
+        "otherwise FALSE." },
+    { "repos_uuid", T_STRING, offsetof(Status3Object, status.repos_uuid), READONLY,
+        "UUID of repository" },
+    { "repos_root_url", T_STRING, offsetof(Status3Object, status.repos_root_url), READONLY,
+        "Repository root URL" },
+    { "repos_relpath", T_STRING, offsetof(Status3Object, status.repos_relpath), READONLY,
+        "Relative path in repository" },
+    /* TODO */
+    { NULL }
+};
+
+static PyTypeObject Status3_Type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "wc.Status", /*   const char *tp_name;  For printing, in format "<module>.<name>" */
+    sizeof(Status3Object),
+    0,/*    Py_ssize_t tp_basicsize, tp_itemsize;  For allocation */
+
+    /* Methods to implement standard operations */
+
+    status_dealloc, /*    destructor tp_dealloc;  */
+    NULL, /*    printfunc tp_print; */
+    NULL, /*    getattrfunc tp_getattr; */
+    NULL, /*    setattrfunc tp_setattr; */
+    NULL, /*    cmpfunc tp_compare; */
+    NULL, /*    reprfunc tp_repr;   */
+
+    /* Method suites for standard classes */
+
+    NULL, /*    PyNumberMethods *tp_as_number;  */
+    NULL, /*    PySequenceMethods *tp_as_sequence;  */
+    NULL, /*    PyMappingMethods *tp_as_mapping;    */
+
+    /* More standard operations (here for binary compatibility) */
+
+    NULL, /*    hashfunc tp_hash;   */
+    NULL, /*    ternaryfunc tp_call;    */
+    NULL, /*    reprfunc tp_str;    */
+    NULL, /*    getattrofunc tp_getattro;   */
+    NULL, /*    setattrofunc tp_setattro;   */
+
+    /* Functions to access object as input/output buffer */
+    NULL, /*    PyBufferProcs *tp_as_buffer;    */
+
+    /* Flags to define presence of optional/expanded features */
+    0, /*   long tp_flags;  */
+
+    NULL, /*    const char *tp_doc;  Documentation string */
+
+    /* Assigned meaning in release 2.0 */
+    /* call function for all accessible objects */
+    NULL, /*    traverseproc tp_traverse;   */
+
+    /* delete references to contained objects */
+    NULL, /*    inquiry tp_clear;   */
+
+    /* Assigned meaning in release 2.1 */
+    /* rich comparisons */
+    NULL, /*    richcmpfunc tp_richcompare; */
+
+    /* weak reference enabler */
+    0, /*   Py_ssize_t tp_weaklistoffset;   */
 
-       if (!PyArg_ParseTuple(args, "s", &name))
-               return NULL;
+    /* Added in release 2.2 */
+    /* Iterators */
+    NULL, /*    getiterfunc tp_iter;    */
+    NULL, /*    iternextfunc tp_iternext;   */
 
-       return PyBool_FromLong(svn_wc_is_wc_prop(name));
-}
+    /* Attribute descriptor and subclassing stuff */
+    NULL, /*    struct PyMethodDef *tp_methods; */
+    status_members, /*    struct PyMemberDef *tp_members; */
+    NULL, /* struct PyGetSetDef *tp_getsetters; */
+};
 
-static PyObject *is_entry_prop(PyObject *self, PyObject *args)
-{
-       char *name;
+static PyObject *py_wc_status(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    ContextObject *context_obj = (ContextObject *)self;
+    char *kwnames[] = {"path", NULL};
+    PyObject *py_path;
+    Status3Object *ret;
+    const char *path;
+    apr_pool_t *scratch_pool, *result_pool;
+    svn_wc_status3_t* status;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwnames, &py_path)) {
+        return NULL;
+    }
+
+    result_pool = Pool(NULL);
+    if (result_pool == NULL) {
+        return NULL;
+    }
+    scratch_pool = Pool(result_pool);
+    if (scratch_pool == NULL) {
+        apr_pool_destroy(result_pool);
+        return NULL;
+    }
+
+    path = py_object_to_svn_abspath(py_path, scratch_pool);
+    if (path == NULL) {
+        apr_pool_destroy(result_pool);
+        return NULL;
+    }
+
+    RUN_SVN_WITH_POOL(result_pool,
+                      svn_wc_status3(&status, context_obj->context, path,
+                                     result_pool, scratch_pool));
+
+    apr_pool_destroy(scratch_pool);
+
+    ret = PyObject_New(Status3Object, &Status3_Type);
+    if (ret == NULL) {
+        apr_pool_destroy(result_pool);
+        return NULL;
+    }
+    ret->pool = result_pool;
+    ret->status = *status;
+    return (PyObject *)ret;
+}
+
+static svn_error_t *py_status_receiver(void *baton, const char *local_abspath,
+                                       const svn_wc_status3_t *status,
+                                       apr_pool_t *scratch_pool)
+{
+    Status3Object *py_status;
+    PyObject *ret;
+    PyGILState_STATE state;
+
+    if (baton == Py_None)
+        return NULL;
+
+    state = PyGILState_Ensure();
+
+    py_status = PyObject_New(Status3Object, &Status3_Type);
+    if (py_status == NULL) {
+        PyGILState_Release(state);
+        return py_svn_error();
+    }
+    py_status->pool = Pool(NULL);
+    py_status->status = *svn_wc_dup_status3(status, py_status->pool);
+
+    ret = PyObject_CallFunction((PyObject *)baton, "sO", local_abspath, py_status);
+    Py_DECREF(py_status);
+
+    if (ret == NULL) {
+        PyGILState_Release(state);
+        return py_svn_error();
+    }
+
+    Py_DECREF(ret);
+    PyGILState_Release(state);
+
+    return NULL;
+}
+
+static PyObject *py_wc_walk_status(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    ContextObject *context_obj = (ContextObject *)self;
+    char *kwnames[] = {"path", "receiver", "depth", "get_all", "no_ignore",
+        "ignore_text_mode", "ignore_patterns", NULL};
+    PyObject *py_path;
+    const char *path;
+    int depth = svn_depth_infinity;
+    bool get_all = true;
+    bool no_ignore = false;
+    bool ignore_text_mode = false;
+    PyObject *py_ignore_patterns = Py_None;
+    PyObject *status_func;
+    apr_array_header_t *ignore_patterns;
+    apr_pool_t *pool;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|ibbbOO", kwnames,
+                                     &py_path, &status_func, &depth, &get_all, &no_ignore,
+                                     &ignore_text_mode, &py_ignore_patterns)) {
+        return NULL;
+    }
+
+    pool = Pool(NULL);
+
+    path = py_object_to_svn_abspath(py_path, pool);
+    if (path == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    if (py_ignore_patterns == Py_None) {
+        ignore_patterns = NULL;
+    } else {
+        if (!string_list_to_apr_array(pool, py_ignore_patterns, &ignore_patterns)) {
+            apr_pool_destroy(pool);
+            return NULL;
+        }
+    }
+
+    RUN_SVN_WITH_POOL(pool,
+                      svn_wc_walk_status(context_obj->context, path, depth,
+                                         get_all, no_ignore, ignore_text_mode,
+                                         ignore_patterns, py_status_receiver,
+                                         status_func, py_cancel_check, NULL,
+                                         pool));
+
+    apr_pool_destroy(pool);
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *py_wc_add_lock(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    ContextObject *context_obj = (ContextObject *)self;
+    PyObject *py_path, *py_lock;
+    svn_lock_t *lock;
+    char *kwnames[] = { "path", "lock", NULL };
+    const char *path;
+    apr_pool_t *scratch_pool;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO!", kwnames, &py_path, &Lock_Type,
+                                     &py_lock)) {
+        return NULL;
+    }
+
+    scratch_pool = Pool(NULL);
+    if (scratch_pool == NULL) {
+        return NULL;
+    }
+
+    path = py_object_to_svn_abspath(py_path, scratch_pool);
+    if (path == NULL) {
+        apr_pool_destroy(scratch_pool);
+        return NULL;
+    }
+
+    lock = py_object_to_svn_lock(py_lock, scratch_pool);
+    if (lock == NULL) {
+        apr_pool_destroy(scratch_pool);
+        return NULL;
+    }
+
+    RUN_SVN_WITH_POOL(scratch_pool,
+                      svn_wc_add_lock2(context_obj->context, path, lock, scratch_pool));
+
+    apr_pool_destroy(scratch_pool);
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *py_wc_remove_lock(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    ContextObject *context_obj = (ContextObject *)self;
+    char *kwnames[] = { "path", NULL };
+    PyObject *py_path;
+    const char *path;
+    apr_pool_t *scratch_pool;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwnames, &py_path)) {
+        return NULL;
+    }
+
+    scratch_pool = Pool(NULL);
+
+    path = py_object_to_svn_abspath(py_path, scratch_pool);
+    if (path == NULL) {
+        apr_pool_destroy(scratch_pool);
+        return NULL;
+    }
+
+    RUN_SVN_WITH_POOL(scratch_pool,
+                      svn_wc_remove_lock2(context_obj->context, path,
+                                          scratch_pool));
+
+    apr_pool_destroy(scratch_pool);
+    Py_RETURN_NONE;
+}
+
+static PyObject *py_wc_add_from_disk(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    ContextObject *context_obj = (ContextObject *)self;
+    char *kwnames[] = {"path", "props", "skip_checks", "notify", NULL };
+    PyObject *py_path;
+    const char *path;
+    bool skip_checks = false;
+    PyObject *py_props = Py_None;
+    PyObject *notify_func = Py_None;
+    apr_pool_t *pool;
+    apr_hash_t *props;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ObO", kwnames,
+                                     &py_path, &py_props, &skip_checks, &notify_func)) {
+        return NULL;
+    }
+
+    pool = Pool(NULL);
+    if (pool == NULL) {
+        return NULL;
+    }
+
+    path = py_object_to_svn_abspath(py_path, pool);
+    if (path == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    if (py_props == Py_None) {
+        props = NULL;
+    } else {
+        props = prop_dict_to_hash(pool, py_props);
+        if (props == NULL) {
+            apr_pool_destroy(pool);
+            return NULL;
+        }
+    }
+
+#if ONLY_SINCE_SVN(1, 9)
+    RUN_SVN_WITH_POOL(
+            pool, svn_wc_add_from_disk3(
+                    context_obj->context, path, props, skip_checks,
+                    notify_func == Py_None?NULL:py_wc_notify_func,
+                    notify_func, pool));
+#else
+    if (props != NULL) {
+        PyErr_SetString(PyExc_NotImplementedError,
+                        "props argument only supported on svn >= 1.9");
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    if (skip_checks) {
+        PyErr_SetString(PyExc_NotImplementedError,
+                        "skip_checks argument only supported on svn >= 1.9");
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+    RUN_SVN_WITH_POOL(
+            pool, svn_wc_add_from_disk(
+                    context_obj->context, path,
+                    notify_func == Py_None?NULL:py_wc_notify_func,
+                    notify_func, pool));
+#endif
 
-       if (!PyArg_ParseTuple(args, "s", &name))
-               return NULL;
+    apr_pool_destroy(pool);
 
-       return PyBool_FromLong(svn_wc_is_entry_prop(name));
+    Py_RETURN_NONE;
 }
 
-static PyObject *get_adm_dir(PyObject *self)
+static PyObject *py_wc_get_prop_diffs(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    ContextObject *context_obj = (ContextObject *)self;
+    PyObject *py_path, *py_orig_props, *py_propchanges;
+    apr_pool_t *pool;
+    char *kwnames[] = {"path", NULL};
+    apr_hash_t *original_props;
+    apr_array_header_t *propchanges;
+    const char *path;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwnames, &py_path)) {
+        return NULL;
+    }
+
+    pool = Pool(NULL);
+
+    path = py_object_to_svn_abspath(py_path, pool);
+    if (path == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    RUN_SVN_WITH_POOL(pool, svn_wc_get_prop_diffs2(&propchanges,
+                                                   &original_props,
+                                                   context_obj->context,
+                                                   path, pool, pool));
+
+    py_orig_props = prop_hash_to_dict(original_props);
+    if (py_orig_props == NULL) {
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+
+    py_propchanges = propchanges_to_list(propchanges);
+    if (py_propchanges == NULL) {
+        apr_pool_destroy(pool);
+        Py_DECREF(py_propchanges);
+        return NULL;
+    }
+
+    apr_pool_destroy(pool);
+
+    return Py_BuildValue("NN", py_orig_props, py_propchanges);
+}
+
+static PyObject *py_wc_context_process_committed_queue(PyObject *self, PyObject *args)
+{
+    apr_pool_t *temp_pool;
+    ContextObject *contextobj = (ContextObject *)self;
+    svn_revnum_t revnum;
+    char *date, *author;
+    PyObject *py_queue;
+
+    if (!PyArg_ParseTuple(args, "O!lss", &CommittedQueue_Type, &py_queue,
+                          &revnum, &date, &author))
+        return NULL;
+
+    temp_pool = Pool(NULL);
+    if (temp_pool == NULL)
+        return NULL;
+
+    svn_wc_committed_queue_t *committed_queue = PyObject_GetCommittedQueue(py_queue);
+
+    RUN_SVN_WITH_POOL(temp_pool,
+                      svn_wc_process_committed_queue2(committed_queue,
+                                                      contextobj->context,
+                                                      revnum, date, author,
+                                                      py_cancel_check, NULL,
+                                                      temp_pool));
+
+    apr_pool_destroy(temp_pool);
+
+    Py_RETURN_NONE;
+}
+
+
+
+static PyMethodDef context_methods[] = {
+    { "locked", py_wc_context_locked, METH_VARARGS,
+        "locked(path) -> (locked_here, locked)\n"
+        "Check whether a patch is locked."},
+    { "check_wc", py_wc_context_check_wc, METH_VARARGS,
+        "check_wc(path) -> wc_format\n"
+        "Check format version of a working copy." },
+    { "text_modified", py_wc_context_text_modified_p2, METH_VARARGS,
+        "text_modified(path) -> bool\n"
+        "Check whether text of a file is modified against base." },
+    { "props_modified", py_wc_context_props_modified_p2, METH_VARARGS,
+        "props_modified(path) -> bool\n"
+        "Check whether props of a file are modified against base." },
+    { "conflicted", py_wc_context_conflicted, METH_VARARGS,
+        "conflicted(path) -> (text_conflicted, prop_conflicted, "
+            "tree_conflicted)\n"
+        "Check whether a path is conflicted." },
+    { "crawl_revisions", (PyCFunction)py_wc_context_crawl_revisions,
+        METH_VARARGS|METH_KEYWORDS,
+        "crawl_revisions(path, reporter, restore_files, depth, "
+            "honor_depth_exclude, depth_compatibility_trick, "
+            "use_commit_time, notify)\n"
+        "Do a depth-first crawl of the working copy." },
+    { "get_update_editor",
+        (PyCFunction)py_wc_context_get_update_editor,
+        METH_VARARGS|METH_KEYWORDS,
+        "get_update_editor(anchor_abspath, target_basename, use_commit_time, "
+            "depth, depth_is_sticky, allow_unver_obstructions, "
+            "adds_as_modification, server_performs_filtering, clean_checkout, "
+            "diff3_cmd, dirent_func=None, conflict_func=None, "
+            "external_func=None) -> target_revnum" },
+    { "ensure_adm",
+        (PyCFunction)py_wc_context_ensure_adm,
+        METH_VARARGS|METH_KEYWORDS,
+        "ensure_adm(local_abspath, url, repos_root_url, repos_uuid, revnum, depth)" },
+    { "process_committed_queue",
+        (PyCFunction)py_wc_context_process_committed_queue,
+        METH_VARARGS|METH_KEYWORDS,
+        "" },
+    { "status",
+        (PyCFunction)py_wc_status,
+        METH_VARARGS|METH_KEYWORDS,
+        "status(path) -> status" },
+    { "walk_status",
+        (PyCFunction)py_wc_walk_status,
+        METH_VARARGS|METH_KEYWORDS,
+        "walk_status(path, receiver, depth=DEPTH_INFINITY, get_all=True, "
+            "no_ignore=False, ignore_text_mode=False, ignore_patterns=None)\n" },
+    { "add_lock",
+        (PyCFunction)py_wc_add_lock,
+        METH_VARARGS|METH_KEYWORDS,
+        "add_lock(path, lock)" },
+    { "remove_lock",
+        (PyCFunction)py_wc_remove_lock,
+        METH_VARARGS|METH_KEYWORDS,
+        "remove_lock(path)" },
+    { "add_from_disk",
+        (PyCFunction)py_wc_add_from_disk,
+        METH_VARARGS|METH_KEYWORDS,
+        "add_from_disk(local_abspath, props=None, skip_checks=False, notify=None)" },
+    { "get_prop_diffs",
+        (PyCFunction)py_wc_get_prop_diffs,
+        METH_VARARGS|METH_KEYWORDS,
+        "get_prop_diffs(path) -> (changes orig_props)" },
+    { NULL }
+};
+
+static void context_dealloc(PyObject *self)
 {
-       apr_pool_t *pool;
-       PyObject *ret;
-       const char *dir;
-       pool = Pool(NULL);
-       if (pool == NULL)
-               return NULL;
-       dir = svn_wc_get_adm_dir(pool);
-       ret = py_object_from_svn_abspath(dir);
-       apr_pool_destroy(pool);
-       return ret;
+    ContextObject *context_obj = (ContextObject *)self;
+    svn_wc_context_destroy(context_obj->context);
+    apr_pool_destroy(context_obj->pool);
+    PyObject_Del(self);
 }
 
-static PyObject *set_adm_dir(PyObject *self, PyObject *args)
+static PyObject *context_init(PyTypeObject *self, PyObject *args, PyObject *kwargs)
 {
-       apr_pool_t *temp_pool;
-       char *name;
-       PyObject *py_name;
+    ContextObject *ret;
+    char *kwnames[] = { NULL };
+    svn_config_t *config = NULL;
 
-       if (!PyArg_ParseTuple(args, "O", &py_name))
-               return NULL;
+    // TODO(jelmer): Support passing in config
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwnames))
+        return NULL;
 
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-       name = py_object_to_svn_string(py_name, temp_pool);
-       if (name == NULL) {
-               apr_pool_destroy(temp_pool);
-               return NULL;
-       }
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_set_adm_dir(name, temp_pool));
-       apr_pool_destroy(temp_pool);
-       Py_RETURN_NONE;
+    ret = PyObject_New(ContextObject, &Context_Type);
+    if (ret == NULL)
+        return NULL;
+
+    ret->pool = Pool(NULL);
+    if (ret->pool == NULL)
+        return NULL;
+    RUN_SVN_WITH_POOL(ret->pool, svn_wc_context_create(&ret->context, config,
+                                                       ret->pool, ret->pool));
+
+    return (PyObject *)ret;
 }
 
-static PyObject *get_pristine_copy_path(PyObject *self, PyObject *args)
-{
-       apr_pool_t *pool;
-       const char *pristine_path;
-       char *path;
-       PyObject *py_path;
-       PyObject *ret;
+static PyTypeObject Context_Type = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       "wc.Context", /*        const char *tp_name;  For printing, in format "<module>.<name>" */
+       sizeof(ContextObject),
+       0,/*    Py_ssize_t tp_basicsize, tp_itemsize;  For allocation */
 
-       if (!PyArg_ParseTuple(args, "O", &py_path))
-               return NULL;
+       /* Methods to implement standard operations */
 
-       pool = Pool(NULL);
-       if (pool == NULL)
-               return NULL;
+       context_dealloc, /*     destructor tp_dealloc;  */
+       NULL, /*        printfunc tp_print;     */
+       NULL, /*        getattrfunc tp_getattr; */
+       NULL, /*        setattrfunc tp_setattr; */
+       NULL, /*        cmpfunc tp_compare;     */
+       NULL, /*        reprfunc tp_repr;       */
 
-       path = py_object_to_svn_string(py_path, pool);
-       if (path == NULL) {
-               apr_pool_destroy(pool);
-               return NULL;
-       }
+       /* Method suites for standard classes */
 
-       PyErr_WarnEx(PyExc_DeprecationWarning, "get_pristine_copy_path is deprecated. Use get_pristine_contents instead.", 2);
-       RUN_SVN_WITH_POOL(pool,
-                 svn_wc_get_pristine_copy_path(svn_dirent_canonicalize(path, pool),
-                                                                               &pristine_path, pool));
-       ret = py_object_from_svn_abspath(pristine_path);
-       apr_pool_destroy(pool);
-       return ret;
-}
+       NULL, /*        PyNumberMethods *tp_as_number;  */
+       NULL, /*        PySequenceMethods *tp_as_sequence;      */
+       NULL, /*        PyMappingMethods *tp_as_mapping;        */
 
-static PyObject *get_pristine_contents(PyObject *self, PyObject *args)
-{
-       char *path;
-       apr_pool_t *temp_pool;
-#if ONLY_SINCE_SVN(1, 6)
-       apr_pool_t *stream_pool;
-       StreamObject *ret;
-       svn_stream_t *stream;
-#else
-       PyObject *ret;
-       const char *pristine_path;
-#endif
+       /* More standard operations (here for binary compatibility) */
 
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
+       NULL, /*        hashfunc tp_hash;       */
+       NULL, /*        ternaryfunc tp_call;    */
+       NULL, /*        reprfunc tp_str;        */
+       NULL, /*        getattrofunc tp_getattro;       */
+       NULL, /*        setattrofunc tp_setattro;       */
 
-#if ONLY_SINCE_SVN(1, 6)
-       stream_pool = Pool(NULL);
-       if (stream_pool == NULL)
-               return NULL;
+       /* Functions to access object as input/output buffer */
+       NULL, /*        PyBufferProcs *tp_as_buffer;    */
 
-       temp_pool = Pool(stream_pool);
-       if (temp_pool == NULL) {
-               apr_pool_destroy(stream_pool);
-               return NULL;
-       }
+       /* Flags to define presence of optional/expanded features */
+       0, /*   long tp_flags;  */
 
-       RUN_SVN_WITH_POOL(stream_pool, svn_wc_get_pristine_contents(&stream, svn_dirent_canonicalize(path, temp_pool), stream_pool, temp_pool));
-       apr_pool_destroy(temp_pool);
+       "Context", /*   const char *tp_doc;  Documentation string */
 
-       if (stream == NULL) {
-               apr_pool_destroy(stream_pool);
-               Py_RETURN_NONE;
-       }
+       /* Assigned meaning in release 2.0 */
+       /* call function for all accessible objects */
+       NULL, /*        traverseproc tp_traverse;       */
 
-       ret = PyObject_New(StreamObject, &Stream_Type);
-       if (ret == NULL)
-               return NULL;
+       /* delete references to contained objects */
+       NULL, /*        inquiry tp_clear;       */
 
-       ret->pool = stream_pool;
-       ret->closed = FALSE;
-       ret->stream = stream;
+       /* Assigned meaning in release 2.1 */
+       /* rich comparisons */
+       NULL, /*        richcmpfunc tp_richcompare;     */
+
+       /* weak reference enabler */
+       0, /*   Py_ssize_t tp_weaklistoffset;   */
+
+       /* Added in release 2.2 */
+       /* Iterators */
+       NULL, /*        getiterfunc tp_iter;    */
+       NULL, /*        iternextfunc tp_iternext;       */
+
+       /* Attribute descriptor and subclassing stuff */
+       context_methods, /*     struct PyMethodDef *tp_methods; */
+       NULL, /*        struct PyMemberDef *tp_members; */
+       NULL, /*        struct PyGetSetDef *tp_getset;  */
+       NULL, /*        struct _typeobject *tp_base;    */
+       NULL, /*        PyObject *tp_dict;      */
+       NULL, /*        descrgetfunc tp_descr_get;      */
+       NULL, /*        descrsetfunc tp_descr_set;      */
+       0, /*   Py_ssize_t tp_dictoffset;       */
+       NULL, /*        initproc tp_init;       */
+       NULL, /*        allocfunc tp_alloc;     */
+       context_init, /*        newfunc tp_new; */
+};
 
-       return (PyObject *)ret;
-#else
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-       RUN_SVN_WITH_POOL(temp_pool, svn_wc_get_pristine_copy_path(svn_dirent_canonicalize(path, temp_pool), &pristine_path, temp_pool));
-       ret = PyFile_FromString((char *)pristine_path, "rb");
-       apr_pool_destroy(temp_pool);
-       return ret;
 #endif
+
+static void lock_dealloc(PyObject *self)
+{
+       LockObject *lockself = (LockObject *)self;
+
+       apr_pool_destroy(lockself->pool);
+
+       PyObject_Del(self);
 }
 
-static PyObject *ensure_adm(PyObject *self, PyObject *args, PyObject *kwargs)
+static PyObject *lock_init(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-       char *path, *uuid, *url;
-       char *repos=NULL;
-       svn_revnum_t rev=-1;
-       apr_pool_t *pool;
-       char *kwnames[] = { "path", "uuid", "url", "repos", "rev", "depth", NULL };
-       svn_depth_t depth = svn_depth_infinity;
+       char *kwnames[] = { "token", NULL };
+       LockObject *ret;
+    char *token = NULL;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|sli", kwnames,
-                                                                        &path, &uuid, &url, &repos, &rev, &depth))
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|z", kwnames, &token))
                return NULL;
 
-       pool = Pool(NULL);
-       if (pool == NULL)
+       ret = PyObject_New(LockObject, &Lock_Type);
+       if (ret == NULL)
                return NULL;
-#if ONLY_SINCE_SVN(1, 5)
-       RUN_SVN_WITH_POOL(pool,
-                                         svn_wc_ensure_adm3(svn_dirent_canonicalize(path, pool),
-                                                                                uuid, url, repos, rev, depth, pool));
-#else
-       if (depth != svn_depth_infinity) {
-               PyErr_SetString(PyExc_NotImplementedError,
-                                               "depth != infinity not supported with svn < 1.5");
-               apr_pool_destroy(pool);
+
+       ret->pool = Pool(NULL);
+       if (ret->pool == NULL)
                return NULL;
-       }
-       RUN_SVN_WITH_POOL(pool,
-                                         svn_wc_ensure_adm2(svn_dirent_canonicalize(path, pool),
-                                                                                uuid, url, repos, rev, pool));
-#endif
-       apr_pool_destroy(pool);
-       Py_RETURN_NONE;
+       ret->lock = *svn_lock_create(ret->pool);
+    if (token != NULL) {
+        ret->lock.token = apr_pstrdup(ret->pool, token);
+    }
+
+       return (PyObject *)ret;
 }
 
-static PyObject *check_wc(PyObject *self, PyObject *args)
-{
-       char *path;
-       apr_pool_t *pool;
-       int wc_format;
+static PyObject *lock_get_path(PyObject *self, void *closure) {
+    LockObject *lock_obj = (LockObject *)self;
 
-       if (!PyArg_ParseTuple(args, "s", &path))
-               return NULL;
+    if (lock_obj->lock.path == NULL) {
+        Py_RETURN_NONE;
+    }
 
-       pool = Pool(NULL);
-       if (pool == NULL)
-               return NULL;
-       RUN_SVN_WITH_POOL(pool, svn_wc_check_wc(svn_dirent_canonicalize(path, pool), &wc_format, pool));
-       apr_pool_destroy(pool);
-       return PyLong_FromLong(wc_format);
+    return PyUnicode_FromString(lock_obj->lock.path);
 }
 
-static PyObject *cleanup_wc(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-       char *path;
-       char *diff3_cmd = NULL;
-       char *kwnames[] = { "path", "diff3_cmd", NULL };
-       apr_pool_t *temp_pool;
+static int lock_set_path(PyObject *self, PyObject *value, void *closure) {
+    LockObject *lock_obj = (LockObject *)self;
+    char *path;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|z", kwnames,
-                                                                        &path, &diff3_cmd))
-               return NULL;
+    path = PyBytes_AsString(value);
+    if (path == NULL) {
+        return -1;
+    }
 
-       temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
-               return NULL;
-       RUN_SVN_WITH_POOL(temp_pool,
-                               svn_wc_cleanup2(path, diff3_cmd, py_cancel_check, NULL,
-                                                               temp_pool));
-       apr_pool_destroy(temp_pool);
+    lock_obj->lock.path = py_object_to_svn_string(value, lock_obj->pool);
+    return 0;
+}
 
-       Py_RETURN_NONE;
+static PyObject *lock_get_token(PyObject *self, void *closure) {
+    LockObject *lock_obj = (LockObject *)self;
+
+    if (lock_obj->lock.token == NULL) {
+        Py_RETURN_NONE;
+    }
+
+    return PyBytes_FromString(lock_obj->lock.token);
 }
 
-static PyObject *match_ignore_list(PyObject *self, PyObject *args)
-{
-#if ONLY_SINCE_SVN(1, 5)
-       char *str;
-       PyObject *py_list;
-       apr_array_header_t *list;
-       apr_pool_t *temp_pool;
-       svn_boolean_t ret;
+static int lock_set_token(PyObject *self, PyObject *value, void *closure) {
+    LockObject *lock_obj = (LockObject *)self;
+    char *token;
 
-       if (!PyArg_ParseTuple(args, "sO", &str, &py_list))
-               return NULL;
+    token = PyBytes_AsString(value);
+    if (token == NULL) {
+        PyErr_SetNone(PyExc_TypeError);
+        return -1;
+    }
 
-       temp_pool = Pool(NULL);
+    lock_obj->lock.token = apr_pstrdup(lock_obj->pool, PyBytes_AsString(value));
+    return 0;
+}
 
-       if (!string_list_to_apr_array(temp_pool, py_list, &list)) {
-               apr_pool_destroy(temp_pool);
-               return NULL;
-       }
+static PyGetSetDef lock_getsetters[] = {
+    { "path", lock_get_path, lock_set_path,
+        "the path this lock applies to"},
+    { "token", lock_get_token, lock_set_token,
+        "unique URI representing lock"},
+    { NULL },
+};
 
-       ret = svn_wc_match_ignore_list(str, list, temp_pool);
+PyTypeObject Lock_Type = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       "wc.Lock", /*   const char *tp_name;  For printing, in format "<module>.<name>" */
+       sizeof(LockObject),
+       0,/*    Py_ssize_t tp_basicsize, tp_itemsize;  For allocation */
 
-       apr_pool_destroy(temp_pool);
+       /* Methods to implement standard operations */
 
-       return PyBool_FromLong(ret);
-#else
-       PyErr_SetNone(PyExc_NotImplementedError);
-       return NULL;
-#endif
-}
+       .tp_dealloc = lock_dealloc, /*  destructor tp_dealloc;  */
 
-static PyMethodDef wc_methods[] = {
-       { "check_wc", check_wc, METH_VARARGS, "check_wc(path) -> version\n"
-               "Check whether path contains a Subversion working copy\n"
-               "return the workdir version"},
-       { "cleanup", (PyCFunction)cleanup_wc, METH_VARARGS|METH_KEYWORDS, "cleanup(path, diff3_cmd=None)\n" },
-       { "ensure_adm", (PyCFunction)ensure_adm, METH_KEYWORDS|METH_VARARGS,
-               "ensure_adm(path, uuid, url, repos=None, rev=None)" },
-       { "get_adm_dir", (PyCFunction)get_adm_dir, METH_NOARGS,
-               "get_adm_dir() -> name" },
-       { "set_adm_dir", (PyCFunction)set_adm_dir, METH_VARARGS,
-               "set_adm_dir(name)" },
-       { "get_pristine_copy_path", get_pristine_copy_path, METH_VARARGS,
-               "get_pristine_copy_path(path) -> path" },
-       { "get_pristine_contents", get_pristine_contents, METH_VARARGS,
-               "get_pristine_contents(path) -> stream" },
-       { "is_adm_dir", is_adm_dir, METH_VARARGS,
-               "is_adm_dir(name) -> bool" },
-       { "is_normal_prop", is_normal_prop, METH_VARARGS,
-               "is_normal_prop(name) -> bool" },
-       { "is_entry_prop", is_entry_prop, METH_VARARGS,
-               "is_entry_prop(name) -> bool" },
-       { "is_wc_prop", is_wc_prop, METH_VARARGS,
-               "is_wc_prop(name) -> bool" },
-       { "revision_status", (PyCFunction)revision_status, METH_KEYWORDS|METH_VARARGS, "revision_status(wc_path, trail_url=None, committed=False) -> (min_rev, max_rev, switched, modified)" },
-       { "version", (PyCFunction)version, METH_NOARGS,
-               "version() -> (major, minor, patch, tag)\n\n"
-               "Version of libsvn_wc currently used."
-       },
-       { "api_version", (PyCFunction)api_version, METH_NOARGS,
-               "api_version() -> (major, minor, patch, tag)\n\n"
-               "Version of libsvn_wc Subvertpy was compiled against."
-       },
-       { "match_ignore_list", (PyCFunction)match_ignore_list, METH_VARARGS,
-               "match_ignore_list(str, patterns) -> bool" },
-       { "get_actual_target", (PyCFunction)get_actual_target, METH_VARARGS,
-               "get_actual_target(path) -> (anchor, target)" },
-       { NULL, }
+       .tp_doc = "Lock", /*    const char *tp_doc;  Documentation string */
+
+       .tp_methods = NULL, /*  struct PyMethodDef *tp_methods; */
+
+       .tp_new = lock_init, /* tp_new tp_new */
+
+    .tp_getset = lock_getsetters,
 };
 
 static PyObject *
@@ -2699,12 +2127,17 @@ moduleinit(void)
        if (PyType_Ready(&Entry_Type) < 0)
                return NULL;
 
-       if (PyType_Ready(&Status_Type) < 0)
+       if (PyType_Ready(&Status2_Type) < 0)
                return NULL;
 
        if (PyType_Ready(&Adm_Type) < 0)
                return NULL;
 
+#if ONLY_SINCE_SVN(1, 7)
+       if (PyType_Ready(&Context_Type) < 0)
+               return NULL;
+#endif
+
        if (PyType_Ready(&Editor_Type) < 0)
                return NULL;
 
@@ -2723,6 +2156,14 @@ moduleinit(void)
        if (PyType_Ready(&CommittedQueue_Type) < 0)
                return NULL;
 
+#if ONLY_SINCE_SVN(1, 7)
+       if (PyType_Ready(&Status3_Type) < 0)
+               return NULL;
+#endif
+
+       if (PyType_Ready(&Lock_Type) < 0)
+               return NULL;
+
        apr_initialize();
 
 #if PY_MAJOR_VERSION >= 3
@@ -2798,15 +2239,18 @@ moduleinit(void)
        PyModule_AddIntConstant(mod, "CONFLICT_CHOOSE_MERGED", svn_wc_conflict_choose_merged);
 #endif
 
-#if ONLY_BEFORE_SVN(1, 7)
-       /* Subversion 1.7 has a couple of significant behaviour changes that break subvertpy.
-        * We haven't updated the code to deal with these changes in behaviour yet.
-        * */
-       PyModule_AddObject(mod, "WorkingCopy", (PyObject *)&Adm_Type);
+       PyModule_AddObject(mod, "Adm", (PyObject *)&Adm_Type);
        Py_INCREF(&Adm_Type);
 
+       PyModule_AddObject(mod, "Lock", (PyObject *)&Lock_Type);
+       Py_INCREF(&Lock_Type);
+
        PyModule_AddObject(mod, "CommittedQueue", (PyObject *)&CommittedQueue_Type);
        Py_INCREF(&CommittedQueue_Type);
+
+#if ONLY_SINCE_SVN(1, 7)
+       PyModule_AddObject(mod, "Context", (PyObject *)&Context_Type);
+       Py_INCREF(&Context_Type);
 #endif
 
        return mod;