summaryrefslogtreecommitdiff
path: root/subversion/libsvn_ra_svn/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_ra_svn/client.c')
-rw-r--r--subversion/libsvn_ra_svn/client.c903
1 files changed, 555 insertions, 348 deletions
diff --git a/subversion/libsvn_ra_svn/client.c b/subversion/libsvn_ra_svn/client.c
index c5c7dd2..335f321 100644
--- a/subversion/libsvn_ra_svn/client.c
+++ b/subversion/libsvn_ra_svn/client.c
@@ -32,6 +32,7 @@
#include <apr_network_io.h>
#include <apr_uri.h>
+#include "svn_hash.h"
#include "svn_types.h"
#include "svn_string.h"
#include "svn_dirent_uri.h"
@@ -49,6 +50,7 @@
#include "svn_private_config.h"
#include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
#include "../libsvn_ra/ra_loader.h"
@@ -202,8 +204,8 @@ static svn_error_t *parse_prop_diffs(const apr_array_header_t *list,
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Prop diffs element not a list"));
prop = apr_array_push(*diffs);
- SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, pool, "c(?s)", &prop->name,
- &prop->value));
+ SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "c(?s)", &prop->name,
+ &prop->value));
}
return SVN_NO_ERROR;
}
@@ -215,9 +217,9 @@ static svn_error_t *parse_lock(const apr_array_header_t *list, apr_pool_t *pool,
{
const char *cdate, *edate;
*lock = svn_lock_create(pool);
- SVN_ERR(svn_ra_svn_parse_tuple(list, pool, "ccc(?c)c(?c)", &(*lock)->path,
- &(*lock)->token, &(*lock)->owner,
- &(*lock)->comment, &cdate, &edate));
+ SVN_ERR(svn_ra_svn__parse_tuple(list, pool, "ccc(?c)c(?c)", &(*lock)->path,
+ &(*lock)->token, &(*lock)->owner,
+ &(*lock)->comment, &cdate, &edate));
(*lock)->path = svn_fspath__canonicalize((*lock)->path, pool);
SVN_ERR(svn_time_from_cstring(&(*lock)->creation_date, cdate, pool));
if (edate)
@@ -231,7 +233,7 @@ svn_error_t *svn_ra_svn__auth_response(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *mech, const char *mech_arg)
{
- return svn_ra_svn_write_tuple(conn, pool, "w(?c)", mech, mech_arg);
+ return svn_ra_svn__write_tuple(conn, pool, "w(?c)", mech, mech_arg);
}
static svn_error_t *handle_auth_request(svn_ra_svn__session_baton_t *sess,
@@ -241,7 +243,7 @@ static svn_error_t *handle_auth_request(svn_ra_svn__session_baton_t *sess,
apr_array_header_t *mechlist;
const char *realm;
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "lc", &mechlist, &realm));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "lc", &mechlist, &realm));
if (mechlist->nelts == 0)
return SVN_NO_ERROR;
return DO_AUTH(sess, mechlist, realm, pool);
@@ -258,9 +260,8 @@ static svn_error_t *ra_svn_set_path(void *baton, const char *path,
{
ra_svn_reporter_baton_t *b = baton;
- SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "set-path", "crb(?c)w",
- path, rev, start_empty, lock_token,
- svn_depth_to_word(depth)));
+ SVN_ERR(svn_ra_svn__write_cmd_set_path(b->conn, pool, path, rev,
+ start_empty, lock_token, depth));
return SVN_NO_ERROR;
}
@@ -269,7 +270,7 @@ static svn_error_t *ra_svn_delete_path(void *baton, const char *path,
{
ra_svn_reporter_baton_t *b = baton;
- SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "delete-path", "c", path));
+ SVN_ERR(svn_ra_svn__write_cmd_delete_path(b->conn, pool, path));
return SVN_NO_ERROR;
}
@@ -283,9 +284,8 @@ static svn_error_t *ra_svn_link_path(void *baton, const char *path,
{
ra_svn_reporter_baton_t *b = baton;
- SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "link-path", "ccrb(?c)w",
- path, url, rev, start_empty, lock_token,
- svn_depth_to_word(depth)));
+ SVN_ERR(svn_ra_svn__write_cmd_link_path(b->conn, pool, path, url, rev,
+ start_empty, lock_token, depth));
return SVN_NO_ERROR;
}
@@ -294,11 +294,11 @@ static svn_error_t *ra_svn_finish_report(void *baton,
{
ra_svn_reporter_baton_t *b = baton;
- SVN_ERR(svn_ra_svn_write_cmd(b->conn, b->pool, "finish-report", ""));
+ SVN_ERR(svn_ra_svn__write_cmd_finish_report(b->conn, b->pool));
SVN_ERR(handle_auth_request(b->sess_baton, b->pool));
SVN_ERR(svn_ra_svn_drive_editor2(b->conn, b->pool, b->editor, b->edit_baton,
NULL, FALSE));
- SVN_ERR(svn_ra_svn_read_cmd_response(b->conn, b->pool, ""));
+ SVN_ERR(svn_ra_svn__read_cmd_response(b->conn, b->pool, ""));
return SVN_NO_ERROR;
}
@@ -307,7 +307,7 @@ static svn_error_t *ra_svn_abort_report(void *baton,
{
ra_svn_reporter_baton_t *b = baton;
- SVN_ERR(svn_ra_svn_write_cmd(b->conn, b->pool, "abort-report", ""));
+ SVN_ERR(svn_ra_svn__write_cmd_abort_report(b->conn, b->pool));
return SVN_NO_ERROR;
}
@@ -319,6 +319,11 @@ static svn_ra_reporter3_t ra_svn_reporter = {
ra_svn_abort_report
};
+/* Set *REPORTER and *REPORT_BATON to a new reporter which will drive
+ * EDITOR/EDIT_BATON when it gets the finish_report() call.
+ *
+ * Allocate the new reporter in POOL.
+ */
static svn_error_t *
ra_svn_get_reporter(svn_ra_svn__session_baton_t *sess_baton,
apr_pool_t *pool,
@@ -377,8 +382,7 @@ static svn_error_t *find_tunnel_agent(const char *tunnel,
int n;
/* Look up the tunnel specification in config. */
- cfg = config ? apr_hash_get(config, SVN_CONFIG_CATEGORY_CONFIG,
- APR_HASH_KEY_STRING) : NULL;
+ cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG) : NULL;
svn_config_get(cfg, &val, SVN_CONFIG_SECTION_TUNNELS, tunnel, NULL);
/* We have one predefined tunnel scheme, if it isn't overridden by config. */
@@ -454,12 +458,13 @@ static void handle_child_process_error(apr_pool_t *pool, apr_status_t status,
|| apr_file_open_stdout(&out_file, pool))
return;
- conn = svn_ra_svn_create_conn2(NULL, in_file, out_file,
- SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
+ conn = svn_ra_svn_create_conn3(NULL, in_file, out_file,
+ SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, 0,
+ 0, pool);
err = svn_error_wrap_apr(status, _("Error in child process: %s"), desc);
- svn_error_clear(svn_ra_svn_write_cmd_failure(conn, pool, err));
+ svn_error_clear(svn_ra_svn__write_cmd_failure(conn, pool, err));
svn_error_clear(err);
- svn_error_clear(svn_ra_svn_flush(conn, pool));
+ svn_error_clear(svn_ra_svn__flush(conn, pool));
}
/* (Note: *CONN is an output parameter.) */
@@ -482,7 +487,9 @@ static svn_error_t *make_tunnel(const char **args, svn_ra_svn_conn_t **conn,
if (status == APR_SUCCESS)
status = apr_proc_create(proc, *args, args, NULL, attr, pool);
if (status != APR_SUCCESS)
- return svn_error_wrap_apr(status, _("Can't create tunnel"));
+ return svn_error_create(SVN_ERR_RA_CANNOT_CREATE_TUNNEL,
+ svn_error_wrap_apr(status,
+ _("Can't create tunnel")), NULL);
/* Arrange for the tunnel agent to get a SIGTERM on pool
* cleanup. This is a little extreme, but the alternatives
@@ -522,9 +529,10 @@ static svn_error_t *make_tunnel(const char **args, svn_ra_svn_conn_t **conn,
apr_file_inherit_unset(proc->out);
/* Guard against dotfile output to stdout on the server. */
- *conn = svn_ra_svn_create_conn2(NULL, proc->out, proc->in,
- SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
- err = svn_ra_svn_skip_leading_garbage(*conn, pool);
+ *conn = svn_ra_svn_create_conn3(NULL, proc->out, proc->in,
+ SVN_DELTA_COMPRESSION_LEVEL_DEFAULT,
+ 0, 0, pool);
+ err = svn_ra_svn__skip_leading_garbage(*conn, pool);
if (err)
return svn_error_quick_wrap(
err,
@@ -592,19 +600,36 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p,
else
{
SVN_ERR(make_connection(uri->hostname, uri->port, &sock, pool));
- conn = svn_ra_svn_create_conn2(sock, NULL, NULL,
+ conn = svn_ra_svn_create_conn3(sock, NULL, NULL,
SVN_DELTA_COMPRESSION_LEVEL_DEFAULT,
- pool);
+ 0, 0, pool);
}
+ /* Build the useragent string, querying the client for any
+ customizations it wishes to note. For historical reasons, we
+ still deliver the hard-coded client version info
+ (SVN_RA_SVN__DEFAULT_USERAGENT) and the customized client string
+ separately in the protocol/capabilities handshake below. But the
+ commit logic wants the combined form for use with the
+ SVN_PROP_TXN_USER_AGENT ephemeral property because that's
+ consistent with our DAV approach. */
+ if (sess->callbacks->get_client_string != NULL)
+ SVN_ERR(sess->callbacks->get_client_string(sess->callbacks_baton,
+ &client_string, pool));
+ if (client_string)
+ sess->useragent = apr_pstrcat(pool, SVN_RA_SVN__DEFAULT_USERAGENT " ",
+ client_string, (char *)NULL);
+ else
+ sess->useragent = SVN_RA_SVN__DEFAULT_USERAGENT;
+
/* Make sure we set conn->session before reading from it,
* because the reader and writer functions expect a non-NULL value. */
sess->conn = conn;
conn->session = sess;
/* Read server's greeting. */
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "nnll", &minver, &maxver,
- &mechlist, &server_caplist));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "nnll", &minver, &maxver,
+ &mechlist, &server_caplist));
/* We support protocol version 2. */
if (minver > 2)
@@ -623,23 +648,21 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p,
return svn_error_create(SVN_ERR_RA_SVN_BAD_VERSION, NULL,
_("Server does not support edit pipelining"));
- if (sess->callbacks->get_client_string != NULL)
- SVN_ERR(sess->callbacks->get_client_string(sess->callbacks_baton,
- &client_string, pool));
-
/* In protocol version 2, we send back our protocol version, our
* capability list, and the URL, and subsequently there is an auth
* request. */
/* Client-side capabilities list: */
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "n(wwwwww)cc(?c)",
- (apr_uint64_t) 2,
- SVN_RA_SVN_CAP_EDIT_PIPELINE,
- SVN_RA_SVN_CAP_SVNDIFF1,
- SVN_RA_SVN_CAP_ABSENT_ENTRIES,
- SVN_RA_SVN_CAP_DEPTH,
- SVN_RA_SVN_CAP_MERGEINFO,
- SVN_RA_SVN_CAP_LOG_REVPROPS,
- url, "SVN/" SVN_VER_NUMBER, client_string));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "n(wwwwww)cc(?c)",
+ (apr_uint64_t) 2,
+ SVN_RA_SVN_CAP_EDIT_PIPELINE,
+ SVN_RA_SVN_CAP_SVNDIFF1,
+ SVN_RA_SVN_CAP_ABSENT_ENTRIES,
+ SVN_RA_SVN_CAP_DEPTH,
+ SVN_RA_SVN_CAP_MERGEINFO,
+ SVN_RA_SVN_CAP_LOG_REVPROPS,
+ url,
+ SVN_RA_SVN__DEFAULT_USERAGENT,
+ client_string));
SVN_ERR(handle_auth_request(sess, pool));
/* This is where the security layer would go into effect if we
@@ -647,8 +670,8 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p,
/* Read the repository's uuid and root URL, and perhaps learn more
capabilities that weren't available before now. */
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "c?c?l", &conn->uuid,
- &conn->repos_root, &repos_caplist));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "c?c?l", &conn->uuid,
+ &conn->repos_root, &repos_caplist));
if (repos_caplist)
SVN_ERR(svn_ra_svn_set_capabilities(conn, repos_caplist));
@@ -679,7 +702,7 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p,
N_("Module for accessing a repository using the svn network protocol.")
#endif
-static const char *ra_svn_get_description(void)
+static const char *ra_svn_get_description(apr_pool_t *pool)
{
return _(RA_SVN_DESCRIPTION);
}
@@ -722,12 +745,10 @@ static svn_error_t *ra_svn_open(svn_ra_session_t *session,
else
tunnel_argv = NULL;
- cfg_client = config ? apr_hash_get(config,
- SVN_CONFIG_CATEGORY_CONFIG,
- APR_HASH_KEY_STRING) : NULL;
- cfg = config ? apr_hash_get(config,
- SVN_CONFIG_CATEGORY_SERVERS,
- APR_HASH_KEY_STRING) : NULL;
+ cfg_client = config
+ ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG)
+ : NULL;
+ cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_SERVERS) : NULL;
svn_auth_set_parameter(callbacks->auth_baton,
SVN_AUTH_PARAM_CONFIG_CATEGORY_CONFIG, cfg_client);
svn_auth_set_parameter(callbacks->auth_baton,
@@ -753,11 +774,11 @@ static svn_error_t *ra_svn_reparent(svn_ra_session_t *ra_session,
svn_ra_svn__session_baton_t *new_sess;
apr_uri_t uri;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "reparent", "c", url));
+ SVN_ERR(svn_ra_svn__write_cmd_reparent(conn, pool, url));
err = handle_auth_request(sess, pool);
if (! err)
{
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, ""));
sess->url = apr_pstrdup(sess->pool, url);
return SVN_NO_ERROR;
}
@@ -802,9 +823,9 @@ static svn_error_t *ra_svn_get_latest_rev(svn_ra_session_t *session,
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-latest-rev", ""));
+ SVN_ERR(svn_ra_svn__write_cmd_get_latest_rev(conn, pool));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "r", rev));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "r", rev));
return SVN_NO_ERROR;
}
@@ -815,10 +836,9 @@ static svn_error_t *ra_svn_get_dated_rev(svn_ra_session_t *session,
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-dated-rev", "c",
- svn_time_to_cstring(tm, pool)));
+ SVN_ERR(svn_ra_svn__write_cmd_get_dated_rev(conn, pool, tm));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "r", rev));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "r", rev));
return SVN_NO_ERROR;
}
@@ -859,14 +879,15 @@ static svn_error_t *ra_svn_change_rev_prop(svn_ra_session_t *session, svn_revnum
}
if (has_atomic_revprops)
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop2", "rc(?s)(b?s)",
- rev, name, value, dont_care, old_value));
+ SVN_ERR(svn_ra_svn__write_cmd_change_rev_prop2(conn, pool, rev, name,
+ value, dont_care,
+ old_value));
else
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop", "rc?s",
- rev, name, value));
+ SVN_ERR(svn_ra_svn__write_cmd_change_rev_prop(conn, pool, rev, name,
+ value));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, ""));
return SVN_NO_ERROR;
}
@@ -900,10 +921,10 @@ static svn_error_t *ra_svn_rev_proplist(svn_ra_session_t *session, svn_revnum_t
svn_ra_svn_conn_t *conn = sess_baton->conn;
apr_array_header_t *proplist;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "rev-proplist", "r", rev));
+ SVN_ERR(svn_ra_svn__write_cmd_rev_proplist(conn, pool, rev));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l", &proplist));
- SVN_ERR(svn_ra_svn_parse_proplist(proplist, pool, props));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "l", &proplist));
+ SVN_ERR(svn_ra_svn__parse_proplist(proplist, pool, props));
return SVN_NO_ERROR;
}
@@ -914,9 +935,9 @@ static svn_error_t *ra_svn_rev_prop(svn_ra_session_t *session, svn_revnum_t rev,
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "rev-prop", "rc", rev, name));
+ SVN_ERR(svn_ra_svn__write_cmd_rev_prop(conn, pool, rev, name));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "(?s)", value));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "(?s)", value));
return SVN_NO_ERROR;
}
@@ -926,8 +947,8 @@ static svn_error_t *ra_svn_end_commit(void *baton)
svn_commit_info_t *commit_info = svn_create_commit_info(ccb->pool);
SVN_ERR(handle_auth_request(ccb->sess_baton, ccb->pool));
- SVN_ERR(svn_ra_svn_read_tuple(ccb->sess_baton->conn, ccb->pool,
- "r(?c)(?c)?(?c)",
+ SVN_ERR(svn_ra_svn__read_tuple(ccb->sess_baton->conn, ccb->pool,
+ "r(?c)(?c)?(?c)",
&(commit_info->revision),
&(commit_info->date),
&(commit_info->author),
@@ -954,9 +975,30 @@ static svn_error_t *ra_svn_commit(svn_ra_session_t *session,
ra_svn_commit_callback_baton_t *ccb;
apr_hash_index_t *hi;
apr_pool_t *iterpool;
- const svn_string_t *log_msg = apr_hash_get(revprop_table,
- SVN_PROP_REVISION_LOG,
- APR_HASH_KEY_STRING);
+ const svn_string_t *log_msg = svn_hash_gets(revprop_table,
+ SVN_PROP_REVISION_LOG);
+
+ if (log_msg == NULL &&
+ ! svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_COMMIT_REVPROPS))
+ {
+ return svn_error_createf(SVN_ERR_BAD_PROPERTY_VALUE, NULL,
+ _("ra_svn does not support not specifying "
+ "a log message with pre-1.5 servers; "
+ "consider passing an empty one, or upgrading "
+ "the server"));
+ }
+ else if (log_msg == NULL)
+ /* 1.5+ server. Set LOG_MSG to something, since the 'logmsg' argument
+ to the 'commit' protocol command is non-optional; on the server side,
+ only REVPROP_TABLE will be used, and LOG_MSG will be ignored. The
+ "svn:log" member of REVPROP_TABLE table is NULL, therefore the commit
+ will have a NULL log message (not just "", really NULL).
+
+ svnserve 1.5.x+ has always ignored LOG_MSG when REVPROP_TABLE was
+ present; this was elevated to a protocol promise in r1498550 (and
+ later documented in this comment) in order to fix the segmentation
+ fault bug described in the log message of r1498550.*/
+ log_msg = svn_string_create("", pool);
/* If we're sending revprops other than svn:log, make sure the server won't
silently ignore them. */
@@ -966,11 +1008,22 @@ static svn_error_t *ra_svn_commit(svn_ra_session_t *session,
_("Server doesn't support setting arbitrary "
"revision properties during commit"));
+ /* If the server supports ephemeral txnprops, add the one that
+ reports the client's version level string. */
+ if (svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_COMMIT_REVPROPS) &&
+ svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS))
+ {
+ svn_hash_sets(revprop_table, SVN_PROP_TXN_CLIENT_COMPAT_VERSION,
+ svn_string_create(SVN_VER_NUMBER, pool));
+ svn_hash_sets(revprop_table, SVN_PROP_TXN_USER_AGENT,
+ svn_string_create(sess_baton->useragent, pool));
+ }
+
/* Tell the server we're starting the commit.
Send log message here for backwards compatibility with servers
before 1.5. */
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(c(!", "commit",
- log_msg->data));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(c(!", "commit",
+ log_msg->data));
if (lock_tokens)
{
iterpool = svn_pool_create(pool);
@@ -984,20 +1037,21 @@ static svn_error_t *ra_svn_commit(svn_ra_session_t *session,
apr_hash_this(hi, &key, NULL, &val);
path = key;
token = val;
- SVN_ERR(svn_ra_svn_write_tuple(conn, iterpool, "cc", path, token));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, iterpool, "cc", path, token));
}
svn_pool_destroy(iterpool);
}
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)b(!", keep_locks));
- SVN_ERR(svn_ra_svn_write_proplist(conn, pool, revprop_table));
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)b(!", keep_locks));
+ SVN_ERR(svn_ra_svn__write_proplist(conn, pool, revprop_table));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, ""));
/* Remember a few arguments for when the commit is over. */
ccb = apr_palloc(pool, sizeof(*ccb));
ccb->sess_baton = sess_baton;
ccb->pool = pool;
+ ccb->new_rev = NULL;
ccb->callback = callback;
ccb->callback_baton = callback_baton;
@@ -1009,6 +1063,79 @@ static svn_error_t *ra_svn_commit(svn_ra_session_t *session,
return SVN_NO_ERROR;
}
+/* Parse IPROPLIST, an array of svn_ra_svn_item_t structures, as a list of
+ const char * repos relative paths and properties for those paths, storing
+ the result as an array of svn_prop_inherited_item_t *items. */
+static svn_error_t *
+parse_iproplist(apr_array_header_t **inherited_props,
+ const apr_array_header_t *iproplist,
+ svn_ra_session_t *session,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+
+{
+ int i;
+ const char *repos_root_url;
+ apr_pool_t *iterpool;
+
+ if (iproplist == NULL)
+ {
+ /* If the server doesn't have the SVN_RA_CAPABILITY_INHERITED_PROPS
+ capability we shouldn't be asking for inherited props, but if we
+ did and the server sent back nothing then we'll want to handle
+ that. */
+ *inherited_props = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(ra_svn_get_repos_root(session, &repos_root_url, scratch_pool));
+
+ *inherited_props = apr_array_make(
+ result_pool, iproplist->nelts, sizeof(svn_prop_inherited_item_t *));
+
+ iterpool = svn_pool_create(scratch_pool);
+
+ for (i = 0; i < iproplist->nelts; i++)
+ {
+ apr_array_header_t *iprop_list;
+ char *parent_rel_path;
+ apr_hash_t *iprops;
+ apr_hash_index_t *hi;
+ svn_prop_inherited_item_t *new_iprop =
+ apr_palloc(result_pool, sizeof(*new_iprop));
+ svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(iproplist, i,
+ svn_ra_svn_item_t);
+ if (elt->kind != SVN_RA_SVN_LIST)
+ return svn_error_create(
+ SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ _("Inherited proplist element not a list"));
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, iterpool, "cl",
+ &parent_rel_path, &iprop_list));
+ SVN_ERR(svn_ra_svn__parse_proplist(iprop_list, iterpool, &iprops));
+ new_iprop->path_or_url = svn_path_url_add_component2(repos_root_url,
+ parent_rel_path,
+ result_pool);
+ new_iprop->prop_hash = apr_hash_make(result_pool);
+ for (hi = apr_hash_first(iterpool, iprops);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *name = svn__apr_hash_index_key(hi);
+ svn_string_t *value = svn__apr_hash_index_val(hi);
+ svn_hash_sets(new_iprop->prop_hash,
+ apr_pstrdup(result_pool, name),
+ svn_string_dup(value, result_pool));
+ }
+ APR_ARRAY_PUSH(*inherited_props, svn_prop_inherited_item_t *) =
+ new_iprop;
+ }
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *ra_svn_get_file(svn_ra_session_t *session, const char *path,
svn_revnum_t rev, svn_stream_t *stream,
svn_revnum_t *fetched_rev,
@@ -1023,17 +1150,17 @@ static svn_error_t *ra_svn_get_file(svn_ra_session_t *session, const char *path,
svn_checksum_ctx_t *checksum_ctx;
apr_pool_t *iterpool;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-file", "c(?r)bb", path,
- rev, (props != NULL), (stream != NULL)));
+ SVN_ERR(svn_ra_svn__write_cmd_get_file(conn, pool, path, rev,
+ (props != NULL), (stream != NULL)));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "(?c)rl",
- &expected_digest,
- &rev, &proplist));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "(?c)rl",
+ &expected_digest,
+ &rev, &proplist));
if (fetched_rev)
*fetched_rev = rev;
if (props)
- SVN_ERR(svn_ra_svn_parse_proplist(proplist, pool, props));
+ SVN_ERR(svn_ra_svn__parse_proplist(proplist, pool, props));
/* We're done if the contents weren't wanted. */
if (!stream)
@@ -1053,7 +1180,7 @@ static svn_error_t *ra_svn_get_file(svn_ra_session_t *session, const char *path,
svn_ra_svn_item_t *item;
svn_pool_clear(iterpool);
- SVN_ERR(svn_ra_svn_read_item(conn, iterpool, &item));
+ SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item));
if (item->kind != SVN_RA_SVN_STRING)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Non-string as part of file contents"));
@@ -1069,7 +1196,7 @@ static svn_error_t *ra_svn_get_file(svn_ra_session_t *session, const char *path,
}
svn_pool_destroy(iterpool);
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, ""));
if (expected_checksum)
{
@@ -1099,31 +1226,31 @@ static svn_error_t *ra_svn_get_dir(svn_ra_session_t *session,
apr_array_header_t *proplist, *dirlist;
int i;
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(c(?r)bb(!", "get-dir", path,
- rev, (props != NULL), (dirents != NULL)));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(c(?r)bb(!", "get-dir", path,
+ rev, (props != NULL), (dirents != NULL)));
if (dirent_fields & SVN_DIRENT_KIND)
- SVN_ERR(svn_ra_svn_write_word(conn, pool, SVN_RA_SVN_DIRENT_KIND));
+ SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_KIND));
if (dirent_fields & SVN_DIRENT_SIZE)
- SVN_ERR(svn_ra_svn_write_word(conn, pool, SVN_RA_SVN_DIRENT_SIZE));
+ SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_SIZE));
if (dirent_fields & SVN_DIRENT_HAS_PROPS)
- SVN_ERR(svn_ra_svn_write_word(conn, pool, SVN_RA_SVN_DIRENT_HAS_PROPS));
+ SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_HAS_PROPS));
if (dirent_fields & SVN_DIRENT_CREATED_REV)
- SVN_ERR(svn_ra_svn_write_word(conn, pool, SVN_RA_SVN_DIRENT_CREATED_REV));
+ SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_CREATED_REV));
if (dirent_fields & SVN_DIRENT_TIME)
- SVN_ERR(svn_ra_svn_write_word(conn, pool, SVN_RA_SVN_DIRENT_TIME));
+ SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_TIME));
if (dirent_fields & SVN_DIRENT_LAST_AUTHOR)
- SVN_ERR(svn_ra_svn_write_word(conn, pool, SVN_RA_SVN_DIRENT_LAST_AUTHOR));
+ SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_LAST_AUTHOR));
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "rll", &rev, &proplist,
- &dirlist));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "rll", &rev, &proplist,
+ &dirlist));
if (fetched_rev)
*fetched_rev = rev;
if (props)
- SVN_ERR(svn_ra_svn_parse_proplist(proplist, pool, props));
+ SVN_ERR(svn_ra_svn__parse_proplist(proplist, pool, props));
/* We're done if dirents aren't wanted. */
if (!dirents)
@@ -1143,11 +1270,11 @@ static svn_error_t *ra_svn_get_dir(svn_ra_session_t *session,
if (elt->kind != SVN_RA_SVN_LIST)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Dirlist element not a list"));
- SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, pool, "cwnbr(?c)(?c)",
- &name, &kind, &size, &has_props,
- &crev, &cdate, &cauthor));
+ SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "cwnbr(?c)(?c)",
+ &name, &kind, &size, &has_props,
+ &crev, &cdate, &cauthor));
name = svn_relpath_canonicalize(name, pool);
- dirent = apr_palloc(pool, sizeof(*dirent));
+ dirent = svn_dirent_create(pool);
dirent->kind = svn_node_kind_from_word(kind);
dirent->size = size;/* FIXME: svn_filesize_t */
dirent->has_props = has_props;
@@ -1165,39 +1292,35 @@ static svn_error_t *ra_svn_get_dir(svn_ra_session_t *session,
else
SVN_ERR(svn_time_from_cstring(&dirent->time, cdate, pool));
dirent->last_author = cauthor;
- apr_hash_set(*dirents, name, APR_HASH_KEY_STRING, dirent);
+ svn_hash_sets(*dirents, name, dirent);
}
return SVN_NO_ERROR;
}
/* Converts a apr_uint64_t with values TRUE, FALSE or
- SVN_RA_SVN_UNSPECIFIED_NUMBER as provided by svn_ra_svn_parse_tuple
+ SVN_RA_SVN_UNSPECIFIED_NUMBER as provided by svn_ra_svn__parse_tuple
to a svn_tristate_t */
static svn_tristate_t
optbool_to_tristate(apr_uint64_t v)
{
- switch (v)
- {
- case TRUE:
- return svn_tristate_true;
- case FALSE:
- return svn_tristate_false;
- default: /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
- return svn_tristate_unknown;
- }
+ if (v == TRUE) /* not just non-zero but exactly equal to 'TRUE' */
+ return svn_tristate_true;
+ if (v == FALSE)
+ return svn_tristate_false;
+
+ return svn_tristate_unknown; /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
}
/* If REVISION is SVN_INVALID_REVNUM, no value is sent to the
server, which defaults to youngest. */
-static svn_error_t *ra_svn_get_mergeinfo(
- svn_ra_session_t *session,
- svn_mergeinfo_catalog_t *catalog,
- const apr_array_header_t *paths,
- svn_revnum_t revision,
- svn_mergeinfo_inheritance_t inherit,
- svn_boolean_t include_descendants,
- apr_pool_t *pool)
+static svn_error_t *ra_svn_get_mergeinfo(svn_ra_session_t *session,
+ svn_mergeinfo_catalog_t *catalog,
+ const apr_array_header_t *paths,
+ svn_revnum_t revision,
+ svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t include_descendants,
+ apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
@@ -1206,18 +1329,18 @@ static svn_error_t *ra_svn_get_mergeinfo(
svn_ra_svn_item_t *elt;
const char *path;
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((!", "get-mergeinfo"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "get-mergeinfo"));
for (i = 0; i < paths->nelts; i++)
{
path = APR_ARRAY_IDX(paths, i, const char *);
- SVN_ERR(svn_ra_svn_write_cstring(conn, pool, path));
+ SVN_ERR(svn_ra_svn__write_cstring(conn, pool, path));
}
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)wb)", revision,
- svn_inheritance_to_word(inherit),
- include_descendants));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)(?r)wb)", revision,
+ svn_inheritance_to_word(inherit),
+ include_descendants));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l", &mergeinfo_tuple));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "l", &mergeinfo_tuple));
*catalog = NULL;
if (mergeinfo_tuple->nelts > 0)
@@ -1232,13 +1355,12 @@ static svn_error_t *ra_svn_get_mergeinfo(
if (elt->kind != SVN_RA_SVN_LIST)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Mergeinfo element is not a list"));
- SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, pool, "cc",
- &path, &to_parse));
+ SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "cc",
+ &path, &to_parse));
SVN_ERR(svn_mergeinfo_parse(&for_path, to_parse, pool));
/* Correct for naughty servers that send "relative" paths
with leading slashes! */
- apr_hash_set(*catalog, path[0] == '/' ? path + 1 : path,
- APR_HASH_KEY_STRING, for_path);
+ svn_hash_sets(*catalog, path[0] == '/' ? path + 1 :path, for_path);
}
}
@@ -1250,17 +1372,20 @@ static svn_error_t *ra_svn_update(svn_ra_session_t *session,
void **report_baton, svn_revnum_t rev,
const char *target, svn_depth_t depth,
svn_boolean_t send_copyfrom_args,
+ svn_boolean_t ignore_ancestry,
const svn_delta_editor_t *update_editor,
- void *update_baton, apr_pool_t *pool)
+ void *update_baton,
+ apr_pool_t *pool,
+ apr_pool_t *scratch_pool)
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
svn_boolean_t recurse = DEPTH_TO_RECURSE(depth);
/* Tell the server we want to start an update. */
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "update", "(?r)cbwb", rev, target,
- recurse, svn_depth_to_word(depth),
- send_copyfrom_args));
+ SVN_ERR(svn_ra_svn__write_cmd_update(conn, pool, rev, target, recurse,
+ depth, send_copyfrom_args,
+ ignore_ancestry));
SVN_ERR(handle_auth_request(sess_baton, pool));
/* Fetch a reporter for the caller to drive. The reporter will drive
@@ -1270,22 +1395,28 @@ static svn_error_t *ra_svn_update(svn_ra_session_t *session,
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_switch(svn_ra_session_t *session,
- const svn_ra_reporter3_t **reporter,
- void **report_baton, svn_revnum_t rev,
- const char *target, svn_depth_t depth,
- const char *switch_url,
- const svn_delta_editor_t *update_editor,
- void *update_baton, apr_pool_t *pool)
+static svn_error_t *
+ra_svn_switch(svn_ra_session_t *session,
+ const svn_ra_reporter3_t **reporter,
+ void **report_baton, svn_revnum_t rev,
+ const char *target, svn_depth_t depth,
+ const char *switch_url,
+ svn_boolean_t send_copyfrom_args,
+ svn_boolean_t ignore_ancestry,
+ const svn_delta_editor_t *update_editor,
+ void *update_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
+ apr_pool_t *pool = result_pool;
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
svn_boolean_t recurse = DEPTH_TO_RECURSE(depth);
/* Tell the server we want to start a switch. */
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "switch", "(?r)cbcw", rev,
- target, recurse, switch_url,
- svn_depth_to_word(depth)));
+ SVN_ERR(svn_ra_svn__write_cmd_switch(conn, pool, rev, target, recurse,
+ switch_url, depth,
+ send_copyfrom_args, ignore_ancestry));
SVN_ERR(handle_auth_request(sess_baton, pool));
/* Fetch a reporter for the caller to drive. The reporter will drive
@@ -1308,9 +1439,8 @@ static svn_error_t *ra_svn_status(svn_ra_session_t *session,
svn_boolean_t recurse = DEPTH_TO_RECURSE(depth);
/* Tell the server we want to start a status operation. */
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "status", "cb(?r)w",
- target, recurse, rev,
- svn_depth_to_word(depth)));
+ SVN_ERR(svn_ra_svn__write_cmd_status(conn, pool, target, recurse, rev,
+ depth));
SVN_ERR(handle_auth_request(sess_baton, pool));
/* Fetch a reporter for the caller to drive. The reporter will drive
@@ -1336,10 +1466,9 @@ static svn_error_t *ra_svn_diff(svn_ra_session_t *session,
svn_boolean_t recurse = DEPTH_TO_RECURSE(depth);
/* Tell the server we want to start a diff. */
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "diff", "(?r)cbbcbw", rev,
- target, recurse, ignore_ancestry,
- versus_url, text_deltas,
- svn_depth_to_word(depth)));
+ SVN_ERR(svn_ra_svn__write_cmd_diff(conn, pool, rev, target, recurse,
+ ignore_ancestry, versus_url,
+ text_deltas, depth));
SVN_ERR(handle_auth_request(sess_baton, pool));
/* Fetch a reporter for the caller to drive. The reporter will drive
@@ -1350,16 +1479,19 @@ static svn_error_t *ra_svn_diff(svn_ra_session_t *session,
}
-static svn_error_t *ra_svn_log(svn_ra_session_t *session,
- const apr_array_header_t *paths,
- svn_revnum_t start, svn_revnum_t end,
- int limit,
- svn_boolean_t discover_changed_paths,
- svn_boolean_t strict_node_history,
- svn_boolean_t include_merged_revisions,
- const apr_array_header_t *revprops,
- svn_log_entry_receiver_t receiver,
- void *receiver_baton, apr_pool_t *pool)
+static svn_error_t *
+perform_ra_svn_log(svn_error_t **outer_error,
+ svn_ra_session_t *session,
+ const apr_array_header_t *paths,
+ svn_revnum_t start, svn_revnum_t end,
+ int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_boolean_t include_merged_revisions,
+ const apr_array_header_t *revprops,
+ svn_log_entry_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
@@ -1370,38 +1502,38 @@ static svn_error_t *ra_svn_log(svn_ra_session_t *session,
char *name;
svn_boolean_t want_custom_revprops;
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((!", "log"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "log"));
if (paths)
{
for (i = 0; i < paths->nelts; i++)
{
path = APR_ARRAY_IDX(paths, i, const char *);
- SVN_ERR(svn_ra_svn_write_cstring(conn, pool, path));
+ SVN_ERR(svn_ra_svn__write_cstring(conn, pool, path));
}
}
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)(?r)bbnb!", start, end,
- discover_changed_paths, strict_node_history,
- (apr_uint64_t) limit,
- include_merged_revisions));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)(?r)(?r)bbnb!", start, end,
+ discover_changed_paths, strict_node_history,
+ (apr_uint64_t) limit,
+ include_merged_revisions));
if (revprops)
{
want_custom_revprops = FALSE;
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!w(!", "revprops"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!w(!", "revprops"));
for (i = 0; i < revprops->nelts; i++)
{
name = APR_ARRAY_IDX(revprops, i, char *);
- SVN_ERR(svn_ra_svn_write_cstring(conn, pool, name));
+ SVN_ERR(svn_ra_svn__write_cstring(conn, pool, name));
if (!want_custom_revprops
&& strcmp(name, SVN_PROP_REVISION_AUTHOR) != 0
&& strcmp(name, SVN_PROP_REVISION_DATE) != 0
&& strcmp(name, SVN_PROP_REVISION_LOG) != 0)
want_custom_revprops = TRUE;
}
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
}
else
{
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!w())", "all-revprops"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!w())", "all-revprops"));
want_custom_revprops = TRUE;
}
@@ -1425,19 +1557,19 @@ static svn_error_t *ra_svn_log(svn_ra_session_t *session,
int nreceived;
svn_pool_clear(iterpool);
- SVN_ERR(svn_ra_svn_read_item(conn, iterpool, &item));
+ SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item));
if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0)
break;
if (item->kind != SVN_RA_SVN_LIST)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Log entry not a list"));
- SVN_ERR(svn_ra_svn_parse_tuple(item->u.list, iterpool,
- "lr(?s)(?s)(?s)?BBnl?B",
- &cplist, &rev, &author, &date,
- &message, &has_children_param,
- &invalid_revnum_param,
- &revprop_count, &rplist,
- &has_subtractive_merge_param));
+ SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, iterpool,
+ "lr(?s)(?s)(?s)?BBnl?B",
+ &cplist, &rev, &author, &date,
+ &message, &has_children_param,
+ &invalid_revnum_param,
+ &revprop_count, &rplist,
+ &has_subtractive_merge_param));
if (want_custom_revprops && rplist == NULL)
{
/* Caller asked for custom revprops, but server is too old. */
@@ -1478,11 +1610,11 @@ static svn_error_t *ra_svn_log(svn_ra_session_t *session,
if (elt->kind != SVN_RA_SVN_LIST)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Changed-path entry not a list"));
- SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, iterpool,
- "cw(?cr)?(?c?BB)",
- &cpath, &action, &copy_path,
- &copy_rev, &kind_str,
- &text_mods, &prop_mods));
+ SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, iterpool,
+ "cw(?cr)?(?c?BB)",
+ &cpath, &action, &copy_path,
+ &copy_rev, &kind_str,
+ &text_mods, &prop_mods));
cpath = svn_fspath__canonicalize(cpath, iterpool);
if (copy_path)
copy_path = svn_fspath__canonicalize(copy_path, iterpool);
@@ -1493,15 +1625,17 @@ static svn_error_t *ra_svn_log(svn_ra_session_t *session,
change->node_kind = svn_node_kind_from_word(kind_str);
change->text_modified = optbool_to_tristate(text_mods);
change->props_modified = optbool_to_tristate(prop_mods);
- apr_hash_set(cphash, cpath, APR_HASH_KEY_STRING, change);
+ svn_hash_sets(cphash, cpath, change);
}
}
else
cphash = NULL;
nreceived = 0;
- if (! (limit && (nest_level == 0) && (++nreceived > limit)))
+ if (! (limit && (nest_level == 0) && (++nreceived > limit))
+ && ! *outer_error)
{
+ svn_error_t *err;
log_entry = svn_log_entry_create(iterpool);
log_entry->changed_paths = cphash;
@@ -1510,22 +1644,22 @@ static svn_error_t *ra_svn_log(svn_ra_session_t *session,
log_entry->has_children = has_children;
log_entry->subtractive_merge = subtractive_merge;
if (rplist)
- SVN_ERR(svn_ra_svn_parse_proplist(rplist, pool,
- &log_entry->revprops));
+ SVN_ERR(svn_ra_svn__parse_proplist(rplist, iterpool,
+ &log_entry->revprops));
if (log_entry->revprops == NULL)
- log_entry->revprops = apr_hash_make(pool);
+ log_entry->revprops = apr_hash_make(iterpool);
if (revprops == NULL)
{
/* Caller requested all revprops; set author/date/log. */
if (author)
- apr_hash_set(log_entry->revprops, SVN_PROP_REVISION_AUTHOR,
- APR_HASH_KEY_STRING, author);
+ svn_hash_sets(log_entry->revprops, SVN_PROP_REVISION_AUTHOR,
+ author);
if (date)
- apr_hash_set(log_entry->revprops, SVN_PROP_REVISION_DATE,
- APR_HASH_KEY_STRING, date);
+ svn_hash_sets(log_entry->revprops, SVN_PROP_REVISION_DATE,
+ date);
if (message)
- apr_hash_set(log_entry->revprops, SVN_PROP_REVISION_LOG,
- APR_HASH_KEY_STRING, message);
+ svn_hash_sets(log_entry->revprops, SVN_PROP_REVISION_LOG,
+ message);
}
else
{
@@ -1534,17 +1668,25 @@ static svn_error_t *ra_svn_log(svn_ra_session_t *session,
{
name = APR_ARRAY_IDX(revprops, i, char *);
if (author && strcmp(name, SVN_PROP_REVISION_AUTHOR) == 0)
- apr_hash_set(log_entry->revprops, SVN_PROP_REVISION_AUTHOR,
- APR_HASH_KEY_STRING, author);
+ svn_hash_sets(log_entry->revprops,
+ SVN_PROP_REVISION_AUTHOR, author);
if (date && strcmp(name, SVN_PROP_REVISION_DATE) == 0)
- apr_hash_set(log_entry->revprops, SVN_PROP_REVISION_DATE,
- APR_HASH_KEY_STRING, date);
+ svn_hash_sets(log_entry->revprops,
+ SVN_PROP_REVISION_DATE, date);
if (message && strcmp(name, SVN_PROP_REVISION_LOG) == 0)
- apr_hash_set(log_entry->revprops, SVN_PROP_REVISION_LOG,
- APR_HASH_KEY_STRING, message);
+ svn_hash_sets(log_entry->revprops,
+ SVN_PROP_REVISION_LOG, message);
}
}
- SVN_ERR(receiver(receiver_baton, log_entry, iterpool));
+ err = receiver(receiver_baton, log_entry, iterpool);
+ if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION)
+ {
+ *outer_error = svn_error_trace(
+ svn_error_compose_create(*outer_error, err));
+ }
+ else
+ SVN_ERR(err);
+
if (log_entry->has_children)
{
nest_level++;
@@ -1559,9 +1701,40 @@ static svn_error_t *ra_svn_log(svn_ra_session_t *session,
svn_pool_destroy(iterpool);
/* Read the response. */
- return svn_ra_svn_read_cmd_response(conn, pool, "");
+ return svn_error_trace(svn_ra_svn__read_cmd_response(conn, pool, ""));
}
+static svn_error_t *
+ra_svn_log(svn_ra_session_t *session,
+ const apr_array_header_t *paths,
+ svn_revnum_t start, svn_revnum_t end,
+ int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_boolean_t include_merged_revisions,
+ const apr_array_header_t *revprops,
+ svn_log_entry_receiver_t receiver,
+ void *receiver_baton, apr_pool_t *pool)
+{
+ svn_error_t *outer_error = NULL;
+ svn_error_t *err;
+
+ err = svn_error_trace(perform_ra_svn_log(&outer_error,
+ session, paths,
+ start, end,
+ limit,
+ discover_changed_paths,
+ strict_node_history,
+ include_merged_revisions,
+ revprops,
+ receiver, receiver_baton,
+ pool));
+ return svn_error_trace(
+ svn_error_compose_create(outer_error,
+ err));
+}
+
+
static svn_error_t *ra_svn_check_path(svn_ra_session_t *session,
const char *path, svn_revnum_t rev,
@@ -1571,9 +1744,9 @@ static svn_error_t *ra_svn_check_path(svn_ra_session_t *session,
svn_ra_svn_conn_t *conn = sess_baton->conn;
const char *kind_word;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "check-path", "c(?r)", path, rev));
+ SVN_ERR(svn_ra_svn__write_cmd_check_path(conn, pool, path, rev));
SVN_ERR(handle_auth_request(sess_baton, pool));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "w", &kind_word));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "w", &kind_word));
*kind = svn_node_kind_from_word(kind_word);
return SVN_NO_ERROR;
}
@@ -1586,7 +1759,7 @@ static svn_error_t *handle_unsupported_cmd(svn_error_t *err,
{
if (err && err->apr_err == SVN_ERR_RA_SVN_UNKNOWN_CMD)
return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err,
- msg);
+ _(msg));
return err;
}
@@ -1600,12 +1773,10 @@ static svn_error_t *ra_svn_stat(svn_ra_session_t *session,
apr_array_header_t *list = NULL;
svn_dirent_t *the_dirent;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "stat", "c(?r)", path, rev));
-
+ SVN_ERR(svn_ra_svn__write_cmd_stat(conn, pool, path, rev));
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool),
- _("'stat' not implemented")));
-
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "(?l)", &list));
+ N_("'stat' not implemented")));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "(?l)", &list));
if (! list)
{
@@ -1618,11 +1789,11 @@ static svn_error_t *ra_svn_stat(svn_ra_session_t *session,
svn_revnum_t crev;
apr_uint64_t size;
- SVN_ERR(svn_ra_svn_parse_tuple(list, pool, "wnbr(?c)(?c)",
- &kind, &size, &has_props,
- &crev, &cdate, &cauthor));
+ SVN_ERR(svn_ra_svn__parse_tuple(list, pool, "wnbr(?c)(?c)",
+ &kind, &size, &has_props,
+ &crev, &cdate, &cauthor));
- the_dirent = apr_palloc(pool, sizeof(*the_dirent));
+ the_dirent = svn_dirent_create(pool);
the_dirent->kind = svn_node_kind_from_word(kind);
the_dirent->size = size;/* FIXME: svn_filesize_t */
the_dirent->has_props = has_props;
@@ -1651,19 +1822,19 @@ static svn_error_t *ra_svn_get_locations(svn_ra_session_t *session,
int i;
/* Transmit the parameters. */
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(cr(!",
- "get-locations", path, peg_revision));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(cr(!",
+ "get-locations", path, peg_revision));
for (i = 0; i < location_revisions->nelts; i++)
{
revision = APR_ARRAY_IDX(location_revisions, i, svn_revnum_t);
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!r!", revision));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!r!", revision));
}
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
/* Servers before 1.1 don't support this command. Check for this here. */
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool),
- _("'get-locations' not implemented")));
+ N_("'get-locations' not implemented")));
/* Read the hash items. */
is_done = FALSE;
@@ -1673,7 +1844,7 @@ static svn_error_t *ra_svn_get_locations(svn_ra_session_t *session,
svn_ra_svn_item_t *item;
const char *ret_path;
- SVN_ERR(svn_ra_svn_read_item(conn, pool, &item));
+ SVN_ERR(svn_ra_svn__read_item(conn, pool, &item));
if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0)
is_done = 1;
else if (item->kind != SVN_RA_SVN_LIST)
@@ -1681,8 +1852,8 @@ static svn_error_t *ra_svn_get_locations(svn_ra_session_t *session,
_("Location entry not a list"));
else
{
- SVN_ERR(svn_ra_svn_parse_tuple(item->u.list, pool, "rc",
- &revision, &ret_path));
+ SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, pool, "rc",
+ &revision, &ret_path));
ret_path = svn_fspath__canonicalize(ret_path, pool);
apr_hash_set(*locations, apr_pmemdup(pool, &revision,
sizeof(revision)),
@@ -1692,7 +1863,7 @@ static svn_error_t *ra_svn_get_locations(svn_ra_session_t *session,
/* Read the response. This is so the server would have a chance to
* report an error. */
- return svn_ra_svn_read_cmd_response(conn, pool, "");
+ return svn_ra_svn__read_cmd_response(conn, pool, "");
}
static svn_error_t *
@@ -1711,13 +1882,14 @@ ra_svn_get_location_segments(svn_ra_session_t *session,
apr_pool_t *iterpool = svn_pool_create(pool);
/* Transmit the parameters. */
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(c(?r)(?r)(?r))",
- "get-location-segments",
- path, peg_revision, start_rev, end_rev));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(c(?r)(?r)(?r))",
+ "get-location-segments",
+ path, peg_revision, start_rev, end_rev));
/* Servers before 1.5 don't support this command. Check for this here. */
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool),
- _("'get-location-segments' not implemented")));
+ N_("'get-location-segments'"
+ " not implemented")));
/* Parse the response. */
is_done = FALSE;
@@ -1728,7 +1900,7 @@ ra_svn_get_location_segments(svn_ra_session_t *session,
const char *ret_path;
svn_pool_clear(iterpool);
- SVN_ERR(svn_ra_svn_read_item(conn, iterpool, &item));
+ SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item));
if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0)
is_done = 1;
else if (item->kind != SVN_RA_SVN_LIST)
@@ -1738,8 +1910,8 @@ ra_svn_get_location_segments(svn_ra_session_t *session,
{
svn_location_segment_t *segment = apr_pcalloc(iterpool,
sizeof(*segment));
- SVN_ERR(svn_ra_svn_parse_tuple(item->u.list, iterpool, "rr(?c)",
- &range_start, &range_end, &ret_path));
+ SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, iterpool, "rr(?c)",
+ &range_start, &range_end, &ret_path));
if (! (SVN_IS_VALID_REVNUM(range_start)
&& SVN_IS_VALID_REVNUM(range_end)))
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
@@ -1756,7 +1928,7 @@ ra_svn_get_location_segments(svn_ra_session_t *session,
/* Read the response. This is so the server would have a chance to
* report an error. */
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, ""));
return SVN_NO_ERROR;
}
@@ -1778,13 +1950,13 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session,
rev_pool = svn_pool_create(pool);
chunk_pool = svn_pool_create(pool);
- SVN_ERR(svn_ra_svn_write_cmd(sess_baton->conn, pool, "get-file-revs",
- "c(?r)(?r)b", path, start, end,
- include_merged_revisions));
+ SVN_ERR(svn_ra_svn__write_cmd_get_file_revs(sess_baton->conn, pool,
+ path, start, end,
+ include_merged_revisions));
/* Servers before 1.1 don't support this command. Check for this here. */
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool),
- _("'get-file-revs' not implemented")));
+ N_("'get-file-revs' not implemented")));
while (1)
{
@@ -1801,7 +1973,7 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session,
svn_pool_clear(rev_pool);
svn_pool_clear(chunk_pool);
- SVN_ERR(svn_ra_svn_read_item(sess_baton->conn, rev_pool, &item));
+ SVN_ERR(svn_ra_svn__read_item(sess_baton->conn, rev_pool, &item));
if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0)
break;
/* Either we've got a correct revision or we will error out below. */
@@ -1810,11 +1982,11 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session,
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Revision entry not a list"));
- SVN_ERR(svn_ra_svn_parse_tuple(item->u.list, rev_pool,
- "crll?B", &p, &rev, &rev_proplist,
- &proplist, &merged_rev_param));
+ SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, rev_pool,
+ "crll?B", &p, &rev, &rev_proplist,
+ &proplist, &merged_rev_param));
p = svn_fspath__canonicalize(p, rev_pool);
- SVN_ERR(svn_ra_svn_parse_proplist(rev_proplist, rev_pool, &rev_props));
+ SVN_ERR(svn_ra_svn__parse_proplist(rev_proplist, rev_pool, &rev_props));
SVN_ERR(parse_prop_diffs(proplist, rev_pool, &props));
if (merged_rev_param == SVN_RA_SVN_UNSPECIFIED_NUMBER)
merged_rev = FALSE;
@@ -1822,7 +1994,7 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session,
merged_rev = (svn_boolean_t) merged_rev_param;
/* Get the first delta chunk so we know if there is a delta. */
- SVN_ERR(svn_ra_svn_read_item(sess_baton->conn, chunk_pool, &item));
+ SVN_ERR(svn_ra_svn__read_item(sess_baton->conn, chunk_pool, &item));
if (item->kind != SVN_RA_SVN_STRING)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Text delta chunk not a string"));
@@ -1851,8 +2023,8 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session,
SVN_ERR(svn_stream_write(stream, item->u.string->data, &size));
svn_pool_clear(chunk_pool);
- SVN_ERR(svn_ra_svn_read_item(sess_baton->conn, chunk_pool,
- &item));
+ SVN_ERR(svn_ra_svn__read_item(sess_baton->conn, chunk_pool,
+ &item));
if (item->kind != SVN_RA_SVN_STRING)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Text delta chunk not a string"));
@@ -1862,7 +2034,7 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session,
}
}
- SVN_ERR(svn_ra_svn_read_cmd_response(sess_baton->conn, pool, ""));
+ SVN_ERR(svn_ra_svn__read_cmd_response(sess_baton->conn, pool, ""));
/* Return error if we didn't get any revisions. */
if (!had_revision)
@@ -1909,16 +2081,15 @@ static svn_error_t *ra_svn_lock_compat(svn_ra_session_t *session,
path = key;
revnum = val;
- SVN_ERR(svn_ra_svn_write_cmd(conn, iterpool, "lock", "c(?c)b(?r)",
- path, comment,
- steal_lock, *revnum));
+ SVN_ERR(svn_ra_svn__write_cmd_lock(conn, iterpool, path, comment,
+ steal_lock, *revnum));
/* Servers before 1.2 doesn't support locking. Check this here. */
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess, pool),
- _("Server doesn't support "
- "the lock command")));
+ N_("Server doesn't support "
+ "the lock command")));
- err = svn_ra_svn_read_cmd_response(conn, iterpool, "l", &list);
+ err = svn_ra_svn__read_cmd_response(conn, iterpool, "l", &list);
if (!err)
SVN_ERR(parse_lock(list, iterpool, &lock));
@@ -1974,15 +2145,15 @@ static svn_error_t *ra_svn_unlock_compat(svn_ra_session_t *session,
else
token = NULL;
- SVN_ERR(svn_ra_svn_write_cmd(conn, iterpool, "unlock", "c(?c)b",
- path, token, break_lock));
+ SVN_ERR(svn_ra_svn__write_cmd_unlock(conn, iterpool, path, token,
+ break_lock));
/* Servers before 1.2 don't support locking. Check this here. */
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess, iterpool),
- _("Server doesn't support the unlock "
- "command")));
+ N_("Server doesn't support the unlock "
+ "command")));
- err = svn_ra_svn_read_cmd_response(conn, iterpool, "");
+ err = svn_ra_svn__read_cmd_response(conn, iterpool, "");
if (err && !SVN_ERR_IS_UNLOCK_ERROR(err))
return err;
@@ -2017,8 +2188,8 @@ static svn_error_t *ra_svn_lock(svn_ra_session_t *session,
svn_error_t *err;
apr_pool_t *iterpool = svn_pool_create(pool);
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((?c)b(!", "lock-many",
- comment, steal_lock));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((?c)b(!", "lock-many",
+ comment, steal_lock));
for (hi = apr_hash_first(pool, path_revs); hi; hi = apr_hash_next(hi))
{
@@ -2032,10 +2203,10 @@ static svn_error_t *ra_svn_lock(svn_ra_session_t *session,
path = key;
revnum = val;
- SVN_ERR(svn_ra_svn_write_tuple(conn, iterpool, "c(?r)", path, *revnum));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, iterpool, "c(?r)", path, *revnum));
}
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
err = handle_auth_request(sess, pool);
@@ -2066,7 +2237,7 @@ static svn_error_t *ra_svn_lock(svn_ra_session_t *session,
path = key;
svn_pool_clear(iterpool);
- SVN_ERR(svn_ra_svn_read_item(conn, iterpool, &elt));
+ SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &elt));
/* The server might have encountered some sort of fatal error in
the middle of the request list. If this happens, it will
@@ -2079,8 +2250,8 @@ static svn_error_t *ra_svn_lock(svn_ra_session_t *session,
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Lock response not a list"));
- SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, iterpool, "wl", &status,
- &list));
+ SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, iterpool, "wl", &status,
+ &list));
if (strcmp(status, "failure") == 0)
err = svn_ra_svn__handle_failure_status(list, iterpool);
@@ -2112,14 +2283,14 @@ static svn_error_t *ra_svn_lock(svn_ra_session_t *session,
{
svn_ra_svn_item_t *elt;
- SVN_ERR(svn_ra_svn_read_item(conn, pool, &elt));
+ SVN_ERR(svn_ra_svn__read_item(conn, pool, &elt));
if (elt->kind != SVN_RA_SVN_WORD || strcmp(elt->u.word, "done") != 0)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Didn't receive end marker for lock "
"responses"));
}
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, ""));
svn_pool_destroy(iterpool);
@@ -2142,8 +2313,8 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session,
svn_error_t *err;
const char *path;
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(b(!", "unlock-many",
- break_lock));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(b(!", "unlock-many",
+ break_lock));
for (hi = apr_hash_first(pool, path_tokens); hi; hi = apr_hash_next(hi))
{
@@ -2160,10 +2331,10 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session,
else
token = NULL;
- SVN_ERR(svn_ra_svn_write_tuple(conn, iterpool, "c(?c)", path, token));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, iterpool, "c(?c)", path, token));
}
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
err = handle_auth_request(sess, pool);
@@ -2191,7 +2362,7 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session,
svn_pool_clear(iterpool);
- SVN_ERR(svn_ra_svn_read_item(conn, iterpool, &elt));
+ SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &elt));
/* The server might have encountered some sort of fatal error in
the middle of the request list. If this happens, it will
@@ -2207,14 +2378,14 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session,
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Unlock response not a list"));
- SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, iterpool, "wl", &status,
- &list));
+ SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, iterpool, "wl", &status,
+ &list));
if (strcmp(status, "failure") == 0)
err = svn_ra_svn__handle_failure_status(list, iterpool);
else if (strcmp(status, "success") == 0)
{
- SVN_ERR(svn_ra_svn_parse_tuple(list, iterpool, "c", &path));
+ SVN_ERR(svn_ra_svn__parse_tuple(list, iterpool, "c", &path));
err = SVN_NO_ERROR;
}
else
@@ -2239,14 +2410,14 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session,
{
svn_ra_svn_item_t *elt;
- SVN_ERR(svn_ra_svn_read_item(conn, pool, &elt));
+ SVN_ERR(svn_ra_svn__read_item(conn, pool, &elt));
if (elt->kind != SVN_RA_SVN_WORD || strcmp(elt->u.word, "done") != 0)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Didn't receive end marker for unlock "
"responses"));
}
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, ""));
svn_pool_destroy(iterpool);
@@ -2262,14 +2433,14 @@ static svn_error_t *ra_svn_get_lock(svn_ra_session_t *session,
svn_ra_svn_conn_t* conn = sess->conn;
apr_array_header_t *list;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-lock", "c", path));
+ SVN_ERR(svn_ra_svn__write_cmd_get_lock(conn, pool, path));
/* Servers before 1.2 doesn't support locking. Check this here. */
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess, pool),
- _("Server doesn't support the get-lock "
- "command")));
+ N_("Server doesn't support the get-lock "
+ "command")));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "(?l)", &list));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "(?l)", &list));
if (list)
SVN_ERR(parse_lock(list, pool, lock));
else
@@ -2288,19 +2459,12 @@ static svn_error_t *path_relative_to_root(svn_ra_session_t *session,
const char *root_url;
SVN_ERR(ra_svn_get_repos_root(session, &root_url, pool));
- if (strcmp(root_url, url) == 0)
- {
- *rel_path = "";
- }
- else
- {
- *rel_path = svn_uri__is_child(root_url, url, pool);
- if (! *rel_path)
- return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
- _("'%s' isn't a child of repository root "
- "URL '%s'"),
- url, root_url);
- }
+ *rel_path = svn_uri_skip_ancestor(root_url, url, pool);
+ if (! *rel_path)
+ return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+ _("'%s' isn't a child of repository root "
+ "URL '%s'"),
+ url, root_url);
return SVN_NO_ERROR;
}
@@ -2321,15 +2485,14 @@ static svn_error_t *ra_svn_get_locks(svn_ra_session_t *session,
SVN_ERR(path_relative_to_root(session, &abs_path, full_url, pool));
abs_path = svn_fspath__canonicalize(abs_path, pool);
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-locks", "c(w)", path,
- svn_depth_to_word(depth)));
+ SVN_ERR(svn_ra_svn__write_cmd_get_locks(conn, pool, path, depth));
/* Servers before 1.2 doesn't support locking. Check this here. */
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess, pool),
- _("Server doesn't support the get-lock "
- "command")));
+ N_("Server doesn't support the get-lock "
+ "command")));
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l", &list));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "l", &list));
*locks = apr_hash_make(pool);
@@ -2355,13 +2518,13 @@ static svn_error_t *ra_svn_get_locks(svn_ra_session_t *session,
*/
if ((strcmp(abs_path, lock->path) == 0) || (depth == svn_depth_infinity))
{
- apr_hash_set(*locks, lock->path, APR_HASH_KEY_STRING, lock);
+ svn_hash_sets(*locks, lock->path, lock);
}
else if ((depth == svn_depth_files) || (depth == svn_depth_immediates))
{
- const char *relpath = svn_fspath__is_child(abs_path, lock->path, pool);
+ const char *relpath = svn_fspath__skip_ancestor(abs_path, lock->path);
if (relpath && (svn_path_component_count(relpath) == 1))
- apr_hash_set(*locks, lock->path, APR_HASH_KEY_STRING, lock);
+ svn_hash_sets(*locks, lock->path, lock);
}
}
@@ -2379,17 +2542,17 @@ static svn_error_t *ra_svn_replay(svn_ra_session_t *session,
{
svn_ra_svn__session_baton_t *sess = session->priv;
- SVN_ERR(svn_ra_svn_write_cmd(sess->conn, pool, "replay", "rrb", revision,
- low_water_mark, send_deltas));
+ SVN_ERR(svn_ra_svn__write_cmd_replay(sess->conn, pool, revision,
+ low_water_mark, send_deltas));
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess, pool),
- _("Server doesn't support the replay "
- "command")));
+ N_("Server doesn't support the replay "
+ "command")));
SVN_ERR(svn_ra_svn_drive_editor2(sess->conn, pool, editor, edit_baton,
NULL, TRUE));
- return svn_ra_svn_read_cmd_response(sess->conn, pool, "");
+ return svn_ra_svn__read_cmd_response(sess->conn, pool, "");
}
@@ -2409,13 +2572,13 @@ ra_svn_replay_range(svn_ra_session_t *session,
svn_revnum_t rev;
svn_boolean_t drive_aborted = FALSE;
- SVN_ERR(svn_ra_svn_write_cmd(sess->conn, pool, "replay-range", "rrrb",
- start_revision, end_revision,
- low_water_mark, send_deltas));
+ SVN_ERR(svn_ra_svn__write_cmd_replay_range(sess->conn, pool,
+ start_revision, end_revision,
+ low_water_mark, send_deltas));
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess, pool),
- _("Server doesn't support the replay-range "
- "command")));
+ N_("Server doesn't support the "
+ "replay-range command")));
iterpool = svn_pool_create(pool);
for (rev = start_revision; rev <= end_revision; rev++)
@@ -2428,14 +2591,14 @@ ra_svn_replay_range(svn_ra_session_t *session,
svn_pool_clear(iterpool);
- SVN_ERR(svn_ra_svn_read_tuple(sess->conn, iterpool,
- "wl", &word, &list));
+ SVN_ERR(svn_ra_svn__read_tuple(sess->conn, iterpool,
+ "wl", &word, &list));
if (strcmp(word, "revprops") != 0)
return svn_error_createf(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Expected 'revprops', found '%s'"),
word);
- SVN_ERR(svn_ra_svn_parse_proplist(list, iterpool, &rev_props));
+ SVN_ERR(svn_ra_svn__parse_proplist(list, iterpool, &rev_props));
SVN_ERR(revstart_func(rev, replay_baton,
&editor, &edit_baton,
@@ -2458,41 +2621,50 @@ ra_svn_replay_range(svn_ra_session_t *session,
}
svn_pool_destroy(iterpool);
- return svn_ra_svn_read_cmd_response(sess->conn, pool, "");
+ return svn_ra_svn__read_cmd_response(sess->conn, pool, "");
}
-static svn_error_t *ra_svn_has_capability(svn_ra_session_t *session,
- svn_boolean_t *has,
- const char *capability,
- apr_pool_t *pool)
+static svn_error_t *
+ra_svn_has_capability(svn_ra_session_t *session,
+ svn_boolean_t *has,
+ const char *capability,
+ apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess = session->priv;
+ static const char* capabilities[][2] =
+ {
+ /* { ra capability string, svn:// wire capability string} */
+ {SVN_RA_CAPABILITY_DEPTH, SVN_RA_SVN_CAP_DEPTH},
+ {SVN_RA_CAPABILITY_MERGEINFO, SVN_RA_SVN_CAP_MERGEINFO},
+ {SVN_RA_CAPABILITY_LOG_REVPROPS, SVN_RA_SVN_CAP_LOG_REVPROPS},
+ {SVN_RA_CAPABILITY_PARTIAL_REPLAY, SVN_RA_SVN_CAP_PARTIAL_REPLAY},
+ {SVN_RA_CAPABILITY_COMMIT_REVPROPS, SVN_RA_SVN_CAP_COMMIT_REVPROPS},
+ {SVN_RA_CAPABILITY_ATOMIC_REVPROPS, SVN_RA_SVN_CAP_ATOMIC_REVPROPS},
+ {SVN_RA_CAPABILITY_INHERITED_PROPS, SVN_RA_SVN_CAP_INHERITED_PROPS},
+ {SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
+ SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS},
+ {SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
+ SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE},
+
+ {NULL, NULL} /* End of list marker */
+ };
+ int i;
*has = FALSE;
- if (strcmp(capability, SVN_RA_CAPABILITY_DEPTH) == 0)
- *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_DEPTH);
- else if (strcmp(capability, SVN_RA_CAPABILITY_MERGEINFO) == 0)
- *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_MERGEINFO);
- else if (strcmp(capability, SVN_RA_CAPABILITY_LOG_REVPROPS) == 0)
- *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_LOG_REVPROPS);
- else if (strcmp(capability, SVN_RA_CAPABILITY_PARTIAL_REPLAY) == 0)
- *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_PARTIAL_REPLAY);
- else if (strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0)
- *has = svn_ra_svn_has_capability(sess->conn,
- SVN_RA_SVN_CAP_COMMIT_REVPROPS);
- else if (strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0)
- *has = svn_ra_svn_has_capability(sess->conn,
- SVN_RA_SVN_CAP_ATOMIC_REVPROPS);
- else /* Don't know any other capabilities, so error. */
+ for (i = 0; capabilities[i][0]; i++)
{
- return svn_error_createf
- (SVN_ERR_UNKNOWN_CAPABILITY, NULL,
- _("Don't know anything about capability '%s'"), capability);
+ if (strcmp(capability, capabilities[i][0]) == 0)
+ {
+ *has = svn_ra_svn_has_capability(sess->conn, capabilities[i][1]);
+ return SVN_NO_ERROR;
+ }
}
- return SVN_NO_ERROR;
+ return svn_error_createf(SVN_ERR_UNKNOWN_CAPABILITY, NULL,
+ _("Don't know anything about capability '%s'"),
+ capability);
}
static svn_error_t *
@@ -2508,16 +2680,49 @@ ra_svn_get_deleted_rev(svn_ra_session_t *session,
svn_ra_svn_conn_t *conn = sess_baton->conn;
/* Transmit the parameters. */
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-deleted-rev", "crr",
- path, peg_revision, end_revision));
+ SVN_ERR(svn_ra_svn__write_cmd_get_deleted_rev(conn, pool, path,
+ peg_revision, end_revision));
/* Servers before 1.6 don't support this command. Check for this here. */
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool),
- _("'get-deleted-rev' not implemented")));
+ N_("'get-deleted-rev' not implemented")));
+
+ return svn_ra_svn__read_cmd_response(conn, pool, "r", revision_deleted);
+}
+
+static svn_error_t *
+ra_svn_register_editor_shim_callbacks(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks)
+{
+ svn_ra_svn__session_baton_t *sess_baton = session->priv;
+ svn_ra_svn_conn_t *conn = sess_baton->conn;
+
+ conn->shim_callbacks = callbacks;
- return svn_ra_svn_read_cmd_response(conn, pool, "r", revision_deleted);
+ return SVN_NO_ERROR;
}
+static svn_error_t *
+ra_svn_get_inherited_props(svn_ra_session_t *session,
+ apr_array_header_t **iprops,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_ra_svn__session_baton_t *sess_baton = session->priv;
+ svn_ra_svn_conn_t *conn = sess_baton->conn;
+ apr_array_header_t *iproplist;
+
+ SVN_ERR(svn_ra_svn__write_cmd_get_iprops(conn, scratch_pool,
+ path, revision));
+ SVN_ERR(handle_auth_request(sess_baton, scratch_pool));
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, scratch_pool, "l", &iproplist));
+ SVN_ERR(parse_iproplist(iprops, iproplist, session, result_pool,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
static const svn_ra__vtable_t ra_svn_vtable = {
svn_ra_svn_version,
@@ -2554,7 +2759,9 @@ static const svn_ra__vtable_t ra_svn_vtable = {
ra_svn_replay,
ra_svn_has_capability,
ra_svn_replay_range,
- ra_svn_get_deleted_rev
+ ra_svn_get_deleted_rev,
+ ra_svn_register_editor_shim_callbacks,
+ ra_svn_get_inherited_props
};
svn_error_t *
@@ -2569,7 +2776,7 @@ svn_ra_svn__init(const svn_version_t *loader_version,
{ NULL, NULL }
};
- SVN_ERR(svn_ver_check_list(svn_ra_svn_version(), checklist));
+ SVN_ERR(svn_ver_check_list2(svn_ra_svn_version(), checklist, svn_ver_equal));
/* Simplified version check to make sure we can safely use the
VTABLE parameter. The RA loader does a more exhaustive check. */