From 652d27b5fa857d990e2e8fd1a9a34a5a863ab83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jelmer=20Vernoo=C4=B3?= Date: Sat, 4 Nov 2023 13:30:25 +0000 Subject: [PATCH 1/2] Initial work on a rust port --- Cargo.lock | 8 ++ Cargo.toml | 3 +- client/Cargo.toml | 11 +++ client/src/lib.rs | 155 +++++++++++++++++++++++++++++++++++ setup.py | 11 +-- subvertpy/client.c | 195 --------------------------------------------- 6 files changed, 180 insertions(+), 203 deletions(-) create mode 100644 client/Cargo.toml create mode 100644 client/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 4f3fc1d5..55c03413 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -655,6 +655,14 @@ dependencies = [ "system-deps", ] +[[package]] +name = "subvertpy-client" +version = "0.1.0" +dependencies = [ + "pyo3", + "subversion", +] + [[package]] name = "subvertpy-subr" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 5dc4720a..56fcd34c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "subr", + "client", ] [workspace.package] @@ -9,5 +10,5 @@ edition = "2021" [workspace.dependencies] pyo3 = { version = ">=0.19", features = ["extension-module"] } -subversion = { verrsion = "0.0.3", features = ["pyo3"] } +subversion = { version = "0.0.3", features = ["pyo3"] } pyo3-file = { git = "https://github.com/omerbenamram/pyo3-file" } diff --git a/client/Cargo.toml b/client/Cargo.toml new file mode 100644 index 00000000..f022db17 --- /dev/null +++ b/client/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "subvertpy-client" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +pyo3 = { workspace = true } +subversion = { workspace = true } diff --git a/client/src/lib.rs b/client/src/lib.rs new file mode 100644 index 00000000..58b91747 --- /dev/null +++ b/client/src/lib.rs @@ -0,0 +1,155 @@ +use pyo3::import_exception; +use pyo3::prelude::*; +use std::collections::HashMap; +use subversion::client::Context; +use subversion::{CommitInfo, Depth, Revision, Revnum}; + +#[pyclass(unsendable)] +pub struct Client(Context); + +import_exception!(subversion, Error); + +fn error_to_pyerr(e: subversion::Error) -> PyErr { + todo!() +} + +#[pymethods] +impl Client { + #[new] + fn new() -> PyResult { + Ok(Client(Context::new().map_err(error_to_pyerr)?)) + } + + fn add( + &self, + path: std::path::PathBuf, + depth: Option, + force: Option, + no_ignore: Option, + add_parents: Option, + no_autoprops: Option, + ) -> PyResult<()> { + self.0 + .add( + path.as_path(), + depth.unwrap_or(Depth::Infinity), + force.unwrap_or(false), + no_ignore.unwrap_or(false), + add_parents.unwrap_or(false), + no_autoprops.unwrap_or(false), + ) + .map_err(error_to_pyerr) + } + + fn checkout( + &mut self, + url: &str, + path: std::path::PathBuf, + rev: Option, + peg_revision: Option, + depth: Option, + ignore_externals: Option, + allow_unver_obstructions: Option, + ) -> PyResult { + self.0 + .checkout( + url, + path.as_path(), + rev.unwrap_or(Revision::Unspecified), + peg_revision.unwrap_or(Revision::Unspecified), + depth.unwrap_or(Depth::Infinity), + ignore_externals.unwrap_or(false), + allow_unver_obstructions.unwrap_or(false), + ) + .map_err(error_to_pyerr) + } + + fn export( + &self, + from: &str, + to: std::path::PathBuf, + rev: Option, + peg_rev: Option, + depth: Option, + ignore_externals: Option, + overwrite: Option, + native_eol: Option, + ignore_keywords: Option, + ) -> PyResult { + self.0 + .export( + from, + to.as_path(), + rev.unwrap_or(Revision::Unspecified), + peg_rev.unwrap_or(Revision::Unspecified), + depth.unwrap_or(Depth::Infinity), + ignore_externals.unwrap_or(false), + overwrite.unwrap_or(false), + native_eol.unwrap_or(false), + ignore_keywords.unwrap_or(false), + ) + .map_err(error_to_pyerr) + } + + fn cat( + &self, + path: &str, + output_stream: PyObject, + rev: Option, + peg_rev: Option, + expand_keywords: Option, + ) -> PyResult<()> { + self.0 + .cat( + path, + output_stream, + rev.unwrap_or(Revision::Unspecified), + peg_rev.unwrap_or(Revision::Unspecified), + expand_keywords.unwrap_or(false), + ) + .map_err(error_to_pyerr) + } + + fn delete( + &self, + paths: Vec<&str>, + force: Option, + keep_local: Option, + revprops: Option>, + commit_cb: Option, + ) -> PyResult<()> { + self.0 + .delete( + paths.as_slice(), + force.unwrap_or(false), + keep_local.unwrap_or(false), + revprops.unwrap_or(HashMap::new()), + |info| { + commit_cb + .as_ref() + .map(|cb| cb.call1((info,))) + .unwrap_or(Ok(None)) + .map_err(error_to_pyerr) + }, + ) + .map_err(error_to_pyerr) + } +} + +#[pyfunction] +fn version() -> PyResult<(i32, i32, i32, &'static str)> { + let version = subversion::client::version(); + Ok(( + version.major(), + version.minor(), + version.patch(), + version.tag(), + )) +} + +#[pymodule] +fn client(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + m.add_wrapped(wrap_pyfunction!(version))?; + Ok(()) +} diff --git a/setup.py b/setup.py index e5c73300..d5d8e21a 100755 --- a/setup.py +++ b/setup.py @@ -224,12 +224,6 @@ def source_path(filename): def subvertpy_modules(): return [ - SvnExtension( - "subvertpy.client", - [source_path(n) - for n in ("client.c", "editor.c", "util.c", "_ra.c", "wc.c")], - libraries=["svn_client-1", "svn_diff-1", "svn_delta-1", - "svn_wc-1", "svn_ra-1", "svn_subr-1"]), SvnExtension( "subvertpy._ra", [source_path(n) for n in ("_ra.c", "util.c", "editor.c")], @@ -278,6 +272,9 @@ def package_data(): ext_modules=subvertpy_modules(), rust_extensions=[ RustExtension( - "subvertpy.subr", "subr/Cargo.toml", binding=Binding.PyO3)], + "subvertpy.subr", "subr/Cargo.toml", binding=Binding.PyO3), + RustExtension( + "subvertpy.client", "client/Cargo.toml", binding=Binding.PyO3), + ], scripts=['bin/subvertpy-fast-export'], ) diff --git a/subvertpy/client.c b/subvertpy/client.c index a84ebf61..ee6a6f79 100644 --- a/subvertpy/client.c +++ b/subvertpy/client.c @@ -534,89 +534,6 @@ static int client_set_config(PyObject *self, PyObject *config, void *closure) return 0; } -static PyObject *client_add(PyObject *self, PyObject *args, PyObject *kwargs) -{ - char *path; - ClientObject *client = (ClientObject *)self; - bool recursive=true, force=false, no_ignore=false; - bool add_parents = false; - bool no_autoprops = false; - apr_pool_t *temp_pool; - char *kwnames[] = { "path", "recursive", "force", "no_ignore", - "add_parents", "no_autoprops", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|bbbbb", kwnames, - &path, &recursive, &force, &no_ignore, &add_parents, &no_autoprops)) - return NULL; - - temp_pool = Pool(NULL); - if (temp_pool == NULL) - return NULL; - - RUN_SVN_WITH_POOL(temp_pool, - svn_client_add5(path, recursive?svn_depth_infinity:svn_depth_empty, - force, no_ignore, no_autoprops, add_parents, - client->client, temp_pool) - ); - - apr_pool_destroy(temp_pool); - Py_RETURN_NONE; -} - -static PyObject *client_checkout(PyObject *self, PyObject *args, PyObject *kwargs) -{ - ClientObject *client = (ClientObject *)self; - char *kwnames[] = { "url", "path", "rev", "peg_rev", "recurse", "ignore_externals", "allow_unver_obstructions", NULL }; - svn_revnum_t result_rev; - svn_opt_revision_t c_peg_rev, c_rev; - const char *path; - const char *url; - PyObject *py_url = NULL, *py_path; - apr_pool_t *temp_pool; - PyObject *peg_rev=Py_None, *rev=Py_None; - bool recurse=true, ignore_externals=false, allow_unver_obstructions=false; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|OObbb", kwnames, - &py_url, &py_path, &rev, &peg_rev, - &recurse, &ignore_externals, - &allow_unver_obstructions)) { - return NULL; - } - - if (!to_opt_revision(peg_rev, &c_peg_rev)) { - return NULL; - } - - if (!to_opt_revision(rev, &c_rev)) { - return NULL; - } - - temp_pool = Pool(NULL); - if (temp_pool == NULL) { - return NULL; - } - - url = py_object_to_svn_uri(py_url, temp_pool); - if (url == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - - path = py_object_to_svn_dirent(py_path, temp_pool); - if (path == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - - RUN_SVN_WITH_POOL(temp_pool, svn_client_checkout3(&result_rev, url, - path, - &c_peg_rev, &c_rev, recurse?svn_depth_infinity:svn_depth_files, - ignore_externals, allow_unver_obstructions, client->client, temp_pool)); - - apr_pool_destroy(temp_pool); - return PyLong_FromLong(result_rev); -} - static svn_error_t *py_commit_callback2(const svn_commit_info_t *commit_info, void *callback, apr_pool_t *pool) { PyObject *py_callback = callback; @@ -715,104 +632,6 @@ static PyObject *client_commit(PyObject *self, PyObject *args, PyObject *kwargs) Py_RETURN_NONE; } -static PyObject *client_export(PyObject *self, PyObject *args, PyObject *kwargs) -{ - ClientObject *client = (ClientObject *)self; - char *kwnames[] = { "from", "to", "rev", "peg_rev", "recurse", "ignore_externals", "overwrite", "native_eol", "ignore_keywords", NULL }; - svn_revnum_t result_rev; - svn_opt_revision_t c_peg_rev, c_rev; - PyObject *py_from, *py_to; - const char *from, *to; - apr_pool_t *temp_pool; - char *native_eol = NULL; - PyObject *peg_rev=Py_None, *rev=Py_None; - bool recurse=true, ignore_externals=false, overwrite=false, ignore_keywords=false; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|OObbbbb", kwnames, &py_from, &py_to, &rev, &peg_rev, &recurse, &ignore_externals, &overwrite, &native_eol, &ignore_keywords)) - return NULL; - - if (!to_opt_revision(peg_rev, &c_peg_rev)) - return NULL; - if (!to_opt_revision(rev, &c_rev)) - return NULL; - - temp_pool = Pool(NULL); - if (temp_pool == NULL) - return NULL; - - from = py_object_to_svn_string(py_from, temp_pool); - if (from == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - - to = py_object_to_svn_dirent(py_to, temp_pool); - if (to == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - - RUN_SVN_WITH_POOL(temp_pool, svn_client_export5(&result_rev, from, to, - &c_peg_rev, &c_rev, overwrite, ignore_externals, ignore_keywords, - recurse?svn_depth_infinity:svn_depth_files, - native_eol, client->client, temp_pool)); - - apr_pool_destroy(temp_pool); - return PyLong_FromLong(result_rev); -} - -static PyObject *client_cat(PyObject *self, PyObject *args, PyObject *kwargs) -{ - ClientObject *client = (ClientObject *)self; - char *kwnames[] = { "path", "output_stream", "revision", "peg_revision", NULL }; - char *path; - PyObject *peg_rev=Py_None, *rev=Py_None; - svn_opt_revision_t c_peg_rev, c_rev; - apr_pool_t *temp_pool; - svn_stream_t *stream; - bool expand_keywords = true; - PyObject *py_stream, *py_path, *ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|OOb", kwnames, &py_path, &py_stream, &rev, &peg_rev, &expand_keywords)) - return NULL; - - if (!to_opt_revision(rev, &c_rev)) - return NULL; - if (!to_opt_revision(peg_rev, &c_peg_rev)) - return NULL; - - temp_pool = Pool(NULL); - if (temp_pool == NULL) { - return NULL; - } - - path = py_object_to_svn_string(py_path, temp_pool); - if (path == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - - stream = new_py_stream(temp_pool, py_stream); - if (stream == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - - apr_hash_t *props = NULL; - RUN_SVN_WITH_POOL(temp_pool, svn_client_cat3( - &props, stream, path, &c_peg_rev, &c_rev, expand_keywords, - client->client, temp_pool, temp_pool)); - - ret = prop_hash_to_dict(props); - if (ret == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - - apr_pool_destroy(temp_pool); - return ret; -} - static PyObject *client_delete(PyObject *self, PyObject *args) { PyObject *paths; @@ -1523,8 +1342,6 @@ static PyObject *client_unlock(PyObject *self, PyObject *args, PyObject *kwargs) } static PyMethodDef client_methods[] = { - { "add", (PyCFunction)client_add, METH_VARARGS|METH_KEYWORDS, - "S.add(path, recursive=True, force=False, no_ignore=False, no_autoprops=False)" }, { "checkout", (PyCFunction)client_checkout, METH_VARARGS|METH_KEYWORDS, "S.checkout(url, path, rev=None, peg_rev=None, recurse=True, ignore_externals=False, allow_unver_obstructions=False)" }, { "export", (PyCFunction)client_export, METH_VARARGS|METH_KEYWORDS, @@ -1974,18 +1791,6 @@ static PyObject *get_config(PyObject *self, PyObject *args) return (PyObject *)data; } -/** - * Get runtime libsvn_wc version information. - * - * :return: tuple with major, minor, patch version number and tag. - */ -static PyObject *version(PyObject *self) -{ - const svn_version_t *ver = svn_client_version(); - return Py_BuildValue("(iiis)", ver->major, ver->minor, - ver->patch, ver->tag); -} - SVN_VERSION_DEFINE(svn_api_version); /** From 434321a71ed96bd8dd7883b1c93d2a7f94e74d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jelmer=20Vernoo=C4=B3?= Date: Sun, 5 Nov 2023 12:48:13 +0000 Subject: [PATCH 2/2] Fix build --- Cargo.lock | 1 + client/Cargo.toml | 1 + client/src/lib.rs | 115 +++++++++++++++++++++++++++++++------- subvertpy/client.c | 136 --------------------------------------------- 4 files changed, 96 insertions(+), 157 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55c03413..1478abb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -660,6 +660,7 @@ name = "subvertpy-client" version = "0.1.0" dependencies = [ "pyo3", + "pyo3-file", "subversion", ] diff --git a/client/Cargo.toml b/client/Cargo.toml index f022db17..cc582960 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -8,4 +8,5 @@ crate-type = ["cdylib"] [dependencies] pyo3 = { workspace = true } +pyo3-file = {workspace =true } subversion = { workspace = true } diff --git a/client/src/lib.rs b/client/src/lib.rs index 58b91747..f0e0c0ee 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -2,14 +2,44 @@ use pyo3::import_exception; use pyo3::prelude::*; use std::collections::HashMap; use subversion::client::Context; -use subversion::{CommitInfo, Depth, Revision, Revnum}; +use subversion::{Depth, Revision, Revnum}; #[pyclass(unsendable)] pub struct Client(Context); +#[pyclass(unsendable)] +pub struct CommitInfo(subversion::CommitInfo); + +#[pymethods] +impl CommitInfo { + #[getter] + fn revision(&self) -> PyResult { + Ok(self.0.revision()) + } + + #[getter] + fn date(&self) -> PyResult<&str> { + Ok(self.0.date()) + } + + #[getter] + fn author(&self) -> PyResult<&str> { + Ok(self.0.author()) + } + + #[getter] + fn post_commit_err(&self) -> PyResult> { + Ok(self.0.post_commit_err()) + } +} + import_exception!(subversion, Error); -fn error_to_pyerr(e: subversion::Error) -> PyErr { +fn error_to_pyerr(_e: subversion::Error) -> PyErr { + todo!() +} + +fn pyerr_to_error(_e: PyErr) -> subversion::Error { todo!() } @@ -21,7 +51,7 @@ impl Client { } fn add( - &self, + &mut self, path: std::path::PathBuf, depth: Option, force: Option, @@ -65,7 +95,7 @@ impl Client { } fn export( - &self, + &mut self, from: &str, to: std::path::PathBuf, rev: Option, @@ -73,36 +103,48 @@ impl Client { depth: Option, ignore_externals: Option, overwrite: Option, - native_eol: Option, + native_eol: Option<&str>, ignore_keywords: Option, ) -> PyResult { self.0 .export( from, to.as_path(), - rev.unwrap_or(Revision::Unspecified), peg_rev.unwrap_or(Revision::Unspecified), - depth.unwrap_or(Depth::Infinity), - ignore_externals.unwrap_or(false), + rev.unwrap_or(Revision::Unspecified), overwrite.unwrap_or(false), - native_eol.unwrap_or(false), + ignore_externals.unwrap_or(false), ignore_keywords.unwrap_or(false), + depth.unwrap_or(Depth::Infinity), + match native_eol { + Some("LF") => subversion::NativeEOL::LF, + Some("CR") => subversion::NativeEOL::CR, + Some("CRLF") => subversion::NativeEOL::CRLF, + None => subversion::NativeEOL::Standard, + _ => { + return Err(pyo3::exceptions::PyValueError::new_err( + "native_eol must be one of 'LF', 'CR', 'CRLF' or None", + )) + } + }, ) .map_err(error_to_pyerr) } fn cat( - &self, + &mut self, path: &str, output_stream: PyObject, rev: Option, peg_rev: Option, expand_keywords: Option, - ) -> PyResult<()> { + ) -> PyResult>> { + let mut output_stream = + pyo3_file::PyFileLikeObject::with_requirements(output_stream, false, true, false)?; self.0 .cat( path, - output_stream, + &mut output_stream, rev.unwrap_or(Revision::Unspecified), peg_rev.unwrap_or(Revision::Unspecified), expand_keywords.unwrap_or(false), @@ -111,7 +153,7 @@ impl Client { } fn delete( - &self, + &mut self, paths: Vec<&str>, force: Option, keep_local: Option, @@ -124,12 +166,43 @@ impl Client { force.unwrap_or(false), keep_local.unwrap_or(false), revprops.unwrap_or(HashMap::new()), - |info| { - commit_cb - .as_ref() - .map(|cb| cb.call1((info,))) - .unwrap_or(Ok(None)) - .map_err(error_to_pyerr) + &|info| -> Result<(), subversion::Error> { + Python::with_gil(|py| { + let commit_info = CommitInfo(info.clone()); + commit_cb + .as_ref() + .map(|cb| cb.call1(py, (commit_info,))) + .transpose() + .map_err(pyerr_to_error) + .map(|_| ()) + }) + }, + ) + .map_err(error_to_pyerr) + } + + pub fn mkdir( + &mut self, + paths: Vec<&str>, + make_parents: Option, + revprops: Option>, + commit_cb: Option, + ) -> PyResult<()> { + self.0 + .mkdir( + paths.as_slice(), + make_parents.unwrap_or(false), + revprops.unwrap_or(HashMap::new()), + &|info| -> Result<(), subversion::Error> { + Python::with_gil(|py| { + let commit_info = CommitInfo(info.clone()); + commit_cb + .as_ref() + .map(|cb| cb.call1(py, (commit_info,))) + .transpose() + .map_err(pyerr_to_error) + .map(|_| ()) + }) }, ) .map_err(error_to_pyerr) @@ -137,13 +210,13 @@ impl Client { } #[pyfunction] -fn version() -> PyResult<(i32, i32, i32, &'static str)> { +fn version() -> PyResult<(i32, i32, i32, String)> { let version = subversion::client::version(); Ok(( version.major(), version.minor(), version.patch(), - version.tag(), + version.tag().to_string(), )) } diff --git a/subvertpy/client.c b/subvertpy/client.c index ee6a6f79..b67a70da 100644 --- a/subvertpy/client.c +++ b/subvertpy/client.c @@ -632,93 +632,6 @@ static PyObject *client_commit(PyObject *self, PyObject *args, PyObject *kwargs) Py_RETURN_NONE; } -static PyObject *client_delete(PyObject *self, PyObject *args) -{ - PyObject *paths; - bool force=false, keep_local=false; - apr_pool_t *temp_pool; - PyObject *py_revprops = Py_None; - apr_array_header_t *apr_paths; - ClientObject *client = (ClientObject *)self; - apr_hash_t *hash_revprops; - PyObject *callback = Py_None; - - if (!PyArg_ParseTuple(args, "O|bbOO", &paths, &force, &keep_local, &py_revprops, &callback)) - return NULL; - - temp_pool = Pool(NULL); - if (temp_pool == NULL) - return NULL; - if (!client_list_to_apr_array(temp_pool, paths, py_object_to_svn_path_or_url, &apr_paths)) { - apr_pool_destroy(temp_pool); - return NULL; - } - - if (py_revprops != Py_None) { - hash_revprops = prop_dict_to_hash(temp_pool, py_revprops); - if (hash_revprops == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - } else { - hash_revprops = NULL; - } - - RUN_SVN_WITH_POOL(temp_pool, svn_client_delete4( - apr_paths, force, keep_local, hash_revprops, py_commit_callback2, callback, client->client, temp_pool)); - - apr_pool_destroy(temp_pool); - - Py_RETURN_NONE; -} - -static PyObject *client_mkdir(PyObject *self, PyObject *args, PyObject *kwargs) -{ - PyObject *paths, *revprops = NULL; - bool make_parents = false; - apr_pool_t *temp_pool; - apr_array_header_t *apr_paths; - apr_hash_t *hash_revprops; - ClientObject *client = (ClientObject *)self; - PyObject *callback = Py_None; - char *kwnames[] = { "path", "make_parents", "revprops", "callback", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|bOO", kwnames, &paths, &make_parents, &revprops, &callback)) - return NULL; - - temp_pool = Pool(NULL); - if (temp_pool == NULL) - return NULL; - if (!client_list_to_apr_array(temp_pool, paths, py_object_to_svn_path_or_url, &apr_paths)) { - apr_pool_destroy(temp_pool); - return NULL; - } - - if (revprops != NULL && !PyDict_Check(revprops)) { - apr_pool_destroy(temp_pool); - PyErr_SetString(PyExc_TypeError, "Expected dictionary with revision properties"); - return NULL; - } - - if (revprops != NULL && revprops != Py_None) { - hash_revprops = prop_dict_to_hash(temp_pool, revprops); - if (hash_revprops == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - } else { - hash_revprops = NULL; - } - - RUN_SVN_WITH_POOL(temp_pool, svn_client_mkdir4(apr_paths, - make_parents?TRUE:FALSE, hash_revprops, py_commit_callback2, callback, - client->client, temp_pool)); - - apr_pool_destroy(temp_pool); - - Py_RETURN_NONE; -} - static PyObject *client_copy(PyObject *self, PyObject *args, PyObject *kwargs) { char *src_path, *dst_path; @@ -872,48 +785,6 @@ static PyObject *client_propget(PyObject *self, PyObject *args) return ret; } -static PyObject *client_proplist(PyObject *self, PyObject *args, - PyObject *kwargs) -{ - char *kwnames[] = { "target", "peg_revision", "depth", "revision", NULL }; - svn_opt_revision_t c_peg_rev; - svn_opt_revision_t c_rev; - int depth; - apr_pool_t *temp_pool; - char *target; - PyObject *peg_revision = Py_None, *revision = Py_None; - ClientObject *client = (ClientObject *)self; - PyObject *prop_list; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOi|O", kwnames, - &target, &peg_revision, &depth, &revision)) - return NULL; - if (!to_opt_revision(peg_revision, &c_peg_rev)) - return NULL; - if (!to_opt_revision(revision, &c_rev)) - return NULL; - temp_pool = Pool(NULL); - if (temp_pool == NULL) - return NULL; - - prop_list = PyList_New(0); - if (prop_list == NULL) { - apr_pool_destroy(temp_pool); - return NULL; - } - - RUN_SVN_WITH_POOL(temp_pool, - svn_client_proplist4(target, &c_peg_rev, &c_rev, - depth, NULL, - false, /* TODO(jelmer): Support get_target_inherited_props */ - proplist_receiver2, prop_list, - client->client, temp_pool)); - - apr_pool_destroy(temp_pool); - - return prop_list; -} - static PyObject *client_resolve(PyObject *self, PyObject *args) { svn_depth_t depth; @@ -1342,12 +1213,6 @@ static PyObject *client_unlock(PyObject *self, PyObject *args, PyObject *kwargs) } static PyMethodDef client_methods[] = { - { "checkout", (PyCFunction)client_checkout, METH_VARARGS|METH_KEYWORDS, - "S.checkout(url, path, rev=None, peg_rev=None, recurse=True, ignore_externals=False, allow_unver_obstructions=False)" }, - { "export", (PyCFunction)client_export, METH_VARARGS|METH_KEYWORDS, - "S.export(from, to, rev=None, peg_rev=None, recurse=True, ignore_externals=False, overwrite=False, native_eol=None)" }, - { "cat", (PyCFunction)client_cat, METH_VARARGS|METH_KEYWORDS, - "S.cat(path, output_stream, revision=None, peg_revision=None)" }, { "commit", (PyCFunction)client_commit, METH_VARARGS|METH_KEYWORDS, "S.commit(targets, recurse=True, keep_locks=True, revprops=None, keep_changelist=False, commit_as_operations=False, include_file_externals=False, include_dir_externals=False, callback=None) -> (revnum, date, author)" }, { "delete", client_delete, METH_VARARGS, "S.delete(paths, force=False)" }, { "copy", (PyCFunction)client_copy, METH_VARARGS|METH_KEYWORDS, "S.copy(src_path, dest_path, srv_rev=None)" }, @@ -1358,7 +1223,6 @@ static PyMethodDef client_methods[] = { { "update", (PyCFunction)client_update, METH_VARARGS|METH_KEYWORDS, "S.update(path, rev=None, recurse=True, ignore_externals=False) -> list of revnums" }, { "list", (PyCFunction)client_list, METH_VARARGS|METH_KEYWORDS, "S.list(path, peg_revision, depth, dirents=ra.DIRENT_ALL, revision=None) -> list of directory entries" }, { "diff", (PyCFunction)client_diff, METH_VARARGS|METH_KEYWORDS, "S.diff(rev1, rev2, path1=None, path2=None, relative_to_dir=None, diffopts=[], encoding=\"utf-8\", ignore_ancestry=True, no_diff_deleted=True, ignore_content_type=False) -> unified diff as a string" }, - { "mkdir", (PyCFunction)client_mkdir, METH_VARARGS|METH_KEYWORDS, "S.mkdir(paths, make_parents=False, revprops=None, callback=None)" }, { "log", (PyCFunction)client_log, METH_VARARGS|METH_KEYWORDS, "S.log(callback, paths, start_rev=None, end_rev=None, limit=0, peg_revision=None, discover_changed_paths=False, strict_node_history=False, include_merged_revisions=False, revprops=None)" }, { "info", (PyCFunction)client_info, METH_VARARGS|METH_KEYWORDS,