You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/11/30 11:24:23 UTC
svn commit: r1717223 [42/50] - in /subversion/branches/ra-git: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/
contrib/hook-scripts/ notes/ notes/api-errata/1.9/ notes/move-tracking/
subversion/ subversion/bindings/ctypes-python/...
Modified: subversion/branches/ra-git/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnserve/serve.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnserve/serve.c (original)
+++ subversion/branches/ra-git/subversion/svnserve/serve.c Mon Nov 30 10:24:16 2015
@@ -627,11 +627,12 @@ create_fs_access(server_baton_t *b, apr_
* On authentication failure, report failure to the client and set
* *success to FALSE. On communications failure, return an error.
* If NEEDS_USERNAME is TRUE, don't allow anonymous authentication. */
-static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+static svn_error_t *auth(svn_boolean_t *success,
+ svn_ra_svn_conn_t *conn,
const char *mech, const char *mecharg,
server_baton_t *b, enum access_type required,
svn_boolean_t needs_username,
- svn_boolean_t *success)
+ apr_pool_t *scratch_pool)
{
const char *user;
*success = FALSE;
@@ -640,10 +641,10 @@ static svn_error_t *auth(svn_ra_svn_conn
&& b->client_info->tunnel_user && strcmp(mech, "EXTERNAL") == 0)
{
if (*mecharg && strcmp(mecharg, b->client_info->tunnel_user) != 0)
- return svn_ra_svn__write_tuple(conn, pool, "w(c)", "failure",
+ return svn_ra_svn__write_tuple(conn, scratch_pool, "w(c)", "failure",
"Requested username does not match");
b->client_info->user = b->client_info->tunnel_user;
- SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w()", "success"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "w()", "success"));
*success = TRUE;
return SVN_NO_ERROR;
}
@@ -651,7 +652,7 @@ static svn_error_t *auth(svn_ra_svn_conn
if (b->repository->anon_access >= required
&& strcmp(mech, "ANONYMOUS") == 0 && ! needs_username)
{
- SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w()", "success"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "w()", "success"));
*success = TRUE;
return SVN_NO_ERROR;
}
@@ -659,13 +660,13 @@ static svn_error_t *auth(svn_ra_svn_conn
if (b->repository->auth_access >= required
&& b->repository->pwdb && strcmp(mech, "CRAM-MD5") == 0)
{
- SVN_ERR(svn_ra_svn_cram_server(conn, pool, b->repository->pwdb,
+ SVN_ERR(svn_ra_svn_cram_server(conn, scratch_pool, b->repository->pwdb,
&user, success));
b->client_info->user = apr_pstrdup(b->pool, user);
return SVN_NO_ERROR;
}
- return svn_ra_svn__write_tuple(conn, pool, "w(c)", "failure",
+ return svn_ra_svn__write_tuple(conn, scratch_pool, "w(c)", "failure",
"Must authenticate with listed mechanism");
}
@@ -677,19 +678,26 @@ internal_auth_request(svn_ra_svn_conn_t
{
svn_boolean_t success;
const char *mech, *mecharg;
+ apr_pool_t *iterpool;
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "success"));
SVN_ERR(send_mechs(conn, pool, b, required, needs_username));
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)c)", b->repository->realm));
+
+ iterpool = svn_pool_create(pool);
do
{
+ svn_pool_clear(iterpool);
+
SVN_ERR(svn_ra_svn__read_tuple(conn, pool, "w(?c)", &mech, &mecharg));
if (!*mech)
break;
- SVN_ERR(auth(conn, pool, mech, mecharg, b, required, needs_username,
- &success));
+ SVN_ERR(auth(&success, conn, mech, mecharg, b, required,
+ needs_username, iterpool));
}
while (!success);
+ svn_pool_destroy(iterpool);
+
return SVN_NO_ERROR;
}
@@ -830,7 +838,7 @@ static svn_error_t *must_have_access(svn
*/
static svn_error_t *set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+ svn_ra_svn__list_t *params, void *baton)
{
report_driver_baton_t *b = baton;
const char *path, *lock_token, *depth_word;
@@ -839,9 +847,9 @@ static svn_error_t *set_path(svn_ra_svn_
svn_depth_t depth = svn_depth_infinity;
svn_boolean_t start_empty;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "crb?(?c)?w",
- &path, &rev, &start_empty, &lock_token,
- &depth_word));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "crb?(?c)?w",
+ &path, &rev, &start_empty, &lock_token,
+ &depth_word));
if (depth_word)
depth = svn_depth_from_word(depth_word);
path = svn_relpath_canonicalize(path, pool);
@@ -857,12 +865,12 @@ static svn_error_t *set_path(svn_ra_svn_
}
static svn_error_t *delete_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+ svn_ra_svn__list_t *params, void *baton)
{
report_driver_baton_t *b = baton;
const char *path;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &path));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &path));
path = svn_relpath_canonicalize(path, pool);
if (!b->err)
b->err = svn_repos_delete_path(b->report_baton, path, pool);
@@ -870,7 +878,7 @@ static svn_error_t *delete_path(svn_ra_s
}
static svn_error_t *link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+ svn_ra_svn__list_t *params, void *baton)
{
report_driver_baton_t *b = baton;
const char *path, *url, *lock_token, *fs_path, *depth_word;
@@ -879,7 +887,7 @@ static svn_error_t *link_path(svn_ra_svn
/* Default to infinity, for old clients that don't send depth. */
svn_depth_t depth = svn_depth_infinity;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccrb?(?c)?w",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "ccrb?(?c)?w",
&path, &url, &rev, &start_empty,
&lock_token, &depth_word));
@@ -901,7 +909,7 @@ static svn_error_t *link_path(svn_ra_svn
}
static svn_error_t *finish_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+ svn_ra_svn__list_t *params, void *baton)
{
report_driver_baton_t *b = baton;
@@ -912,8 +920,11 @@ static svn_error_t *finish_report(svn_ra
return SVN_NO_ERROR;
}
-static svn_error_t *abort_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+abort_report(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
report_driver_baton_t *b = baton;
@@ -922,12 +933,12 @@ static svn_error_t *abort_report(svn_ra_
return SVN_NO_ERROR;
}
-static const svn_ra_svn_cmd_entry_t report_commands[] = {
+static const svn_ra_svn__cmd_entry_t report_commands[] = {
{ "set-path", set_path },
{ "delete-path", delete_path },
{ "link-path", link_path },
- { "finish-report", finish_report, TRUE },
- { "abort-report", abort_report, TRUE },
+ { "finish-report", finish_report, NULL, TRUE },
+ { "abort-report", abort_report, NULL, TRUE },
{ NULL }
};
@@ -1092,14 +1103,17 @@ get_props(apr_hash_t **props,
}
/* Set BATON->FS_PATH for the repository URL found in PARAMS. */
-static svn_error_t *reparent(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+reparent(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
const char *url;
const char *fs_path;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &url));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &url));
url = svn_uri_canonicalize(url, pool);
SVN_ERR(trivial_auth_request(conn, pool, b));
SVN_CMD_ERR(get_fs_path(svn_path_uri_decode(b->repository->repos_url, pool),
@@ -1111,8 +1125,11 @@ static svn_error_t *reparent(svn_ra_svn_
return SVN_NO_ERROR;
}
-static svn_error_t *get_latest_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+get_latest_rev(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -1125,15 +1142,18 @@ static svn_error_t *get_latest_rev(svn_r
return SVN_NO_ERROR;
}
-static svn_error_t *get_dated_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+get_dated_rev(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
apr_time_t tm;
const char *timestr;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", ×tr));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c", ×tr));
SVN_ERR(log_command(b, conn, pool, "get-dated-rev %s", timestr));
SVN_ERR(trivial_auth_request(conn, pool, b));
@@ -1171,8 +1191,11 @@ static svn_error_t *do_change_rev_prop(s
return SVN_NO_ERROR;
}
-static svn_error_t *change_rev_prop2(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+change_rev_prop2(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -1182,7 +1205,7 @@ static svn_error_t *change_rev_prop2(svn
svn_string_t *old_value;
svn_boolean_t dont_care;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rc(?s)(b?s)",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "rc(?s)(b?s)",
&rev, &name, &value,
&dont_care, &old_value));
@@ -1208,8 +1231,11 @@ static svn_error_t *change_rev_prop2(svn
return SVN_NO_ERROR;
}
-static svn_error_t *change_rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+change_rev_prop(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -1218,15 +1244,18 @@ static svn_error_t *change_rev_prop(svn_
/* Because the revprop value was at one time mandatory, the usual
optional element pattern "(?s)" isn't used. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rc?s", &rev, &name, &value));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "rc?s", &rev, &name, &value));
SVN_ERR(do_change_rev_prop(conn, b, rev, name, NULL, value, pool));
return SVN_NO_ERROR;
}
-static svn_error_t *rev_proplist(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+rev_proplist(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -1236,7 +1265,7 @@ static svn_error_t *rev_proplist(svn_ra_
ab.server = b;
ab.conn = conn;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "r", &rev));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "r", &rev));
SVN_ERR(log_command(b, conn, pool, "%s", svn_log__rev_proplist(rev, pool)));
SVN_ERR(trivial_auth_request(conn, pool, b));
@@ -1250,8 +1279,11 @@ static svn_error_t *rev_proplist(svn_ra_
return SVN_NO_ERROR;
}
-static svn_error_t *rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+rev_prop(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -1262,7 +1294,7 @@ static svn_error_t *rev_prop(svn_ra_svn_
ab.server = b;
ab.conn = conn;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rc", &rev, &name));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "rc", &rev, &name));
SVN_ERR(log_command(b, conn, pool, "%s",
svn_log__rev_prop(rev, name, pool)));
@@ -1291,14 +1323,15 @@ static svn_error_t *commit_done(const sv
/* Add the LOCK_TOKENS (if any) to the filesystem access context,
* checking path authorizations using the state in SB as we go.
- * LOCK_TOKENS is an array of svn_ra_svn_item_t structs. Return a
+ * LOCK_TOKENS is an array of svn_ra_svn__item_t structs. Return a
* client error if LOCK_TOKENS is not a list of lists. If a lock
* violates the authz configuration, return SVN_ERR_RA_NOT_AUTHORIZED
* to the client. Use POOL for temporary allocations only.
*/
-static svn_error_t *add_lock_tokens(const apr_array_header_t *lock_tokens,
- server_baton_t *sb,
- apr_pool_t *pool)
+static svn_error_t *
+add_lock_tokens(const svn_ra_svn__list_t *lock_tokens,
+ server_baton_t *sb,
+ apr_pool_t *pool)
{
int i;
svn_fs_access_t *fs_access;
@@ -1312,24 +1345,23 @@ static svn_error_t *add_lock_tokens(cons
for (i = 0; i < lock_tokens->nelts; ++i)
{
const char *path, *token, *full_path;
- svn_ra_svn_item_t *path_item, *token_item;
- svn_ra_svn_item_t *item = &APR_ARRAY_IDX(lock_tokens, i,
- svn_ra_svn_item_t);
+ svn_ra_svn__item_t *path_item, *token_item;
+ svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(lock_tokens, i);
if (item->kind != SVN_RA_SVN_LIST)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
"Lock tokens aren't a list of lists");
- path_item = &APR_ARRAY_IDX(item->u.list, 0, svn_ra_svn_item_t);
+ path_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 0);
if (path_item->kind != SVN_RA_SVN_STRING)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
"Lock path isn't a string");
- token_item = &APR_ARRAY_IDX(item->u.list, 1, svn_ra_svn_item_t);
+ token_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 1);
if (token_item->kind != SVN_RA_SVN_STRING)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
"Lock token isn't a string");
- path = path_item->u.string->data;
+ path = path_item->u.string.data;
full_path = svn_fspath__join(sb->repository->fs_path->data,
svn_relpath_canonicalize(path, pool),
pool);
@@ -1338,7 +1370,7 @@ static svn_error_t *add_lock_tokens(cons
return error_create_and_log(SVN_ERR_RA_NOT_AUTHORIZED, NULL, NULL,
sb);
- token = token_item->u.string->data;
+ token = token_item->u.string.data;
SVN_ERR(svn_fs_access_add_lock_token2(fs_access, path, token));
}
@@ -1361,10 +1393,11 @@ lock_cb(void *baton,
}
/* Unlock the paths with lock tokens in LOCK_TOKENS, ignoring any errors.
- LOCK_TOKENS contains svn_ra_svn_item_t elements, assumed to be lists. */
-static svn_error_t *unlock_paths(const apr_array_header_t *lock_tokens,
- server_baton_t *sb,
- apr_pool_t *pool)
+ LOCK_TOKENS contains svn_ra_svn__item_t elements, assumed to be lists. */
+static svn_error_t *
+unlock_paths(const svn_ra_svn__list_t *lock_tokens,
+ server_baton_t *sb,
+ apr_pool_t *pool)
{
int i;
apr_pool_t *subpool = svn_pool_create(pool);
@@ -1373,18 +1406,18 @@ static svn_error_t *unlock_paths(const a
for (i = 0; i < lock_tokens->nelts; ++i)
{
- svn_ra_svn_item_t *item, *path_item, *token_item;
+ svn_ra_svn__item_t *item, *path_item, *token_item;
const char *path, *token, *full_path;
- item = &APR_ARRAY_IDX(lock_tokens, i, svn_ra_svn_item_t);
- path_item = &APR_ARRAY_IDX(item->u.list, 0, svn_ra_svn_item_t);
- token_item = &APR_ARRAY_IDX(item->u.list, 1, svn_ra_svn_item_t);
+ item = &SVN_RA_SVN__LIST_ITEM(lock_tokens, i);
+ path_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 0);
+ token_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 1);
- path = path_item->u.string->data;
+ path = path_item->u.string.data;
full_path = svn_fspath__join(sb->repository->fs_path->data,
svn_relpath_canonicalize(path, subpool),
subpool);
- token = token_item->u.string->data;
+ token = token_item->u.string.data;
svn_hash_sets(targets, full_path, token);
}
@@ -1401,17 +1434,20 @@ static svn_error_t *unlock_paths(const a
return SVN_NO_ERROR;
}
-static svn_error_t *commit(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+commit(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
const char *log_msg,
*date = NULL,
*author = NULL,
*post_commit_err = NULL;
- apr_array_header_t *lock_tokens;
+ svn_ra_svn__list_t *lock_tokens;
svn_boolean_t keep_locks;
- apr_array_header_t *revprop_list;
+ svn_ra_svn__list_t *revprop_list;
apr_hash_t *revprop_table;
const svn_delta_editor_t *editor;
void *edit_baton;
@@ -1427,7 +1463,7 @@ static svn_error_t *commit(svn_ra_svn_co
{
/* Clients before 1.2 don't send lock-tokens, keep-locks,
and rev-props fields. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &log_msg));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &log_msg));
lock_tokens = NULL;
keep_locks = TRUE;
revprop_list = NULL;
@@ -1435,7 +1471,7 @@ static svn_error_t *commit(svn_ra_svn_co
else
{
/* Clients before 1.5 don't send the rev-props field. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "clb?l", &log_msg,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "clb?l", &log_msg,
&lock_tokens, &keep_locks,
&revprop_list));
}
@@ -1513,8 +1549,11 @@ static svn_error_t *commit(svn_ra_svn_co
return SVN_NO_ERROR;
}
-static svn_error_t *get_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+get_file(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
const char *path, *full_path, *hex_digest;
@@ -1537,7 +1576,7 @@ static svn_error_t *get_file(svn_ra_svn_
ab.conn = conn;
/* Parse arguments. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)bb?B", &path, &rev,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)bb?B", &path, &rev,
&want_props, &want_contents,
&wants_inherited_props));
@@ -1637,9 +1676,25 @@ static svn_error_t *get_file(svn_ra_svn_
return SVN_NO_ERROR;
}
-static svn_error_t *get_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
-{
+static svn_error_t *
+get_dir(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
+{
+ static const svn_string_t str_kind
+ = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_KIND);
+ static const svn_string_t str_size
+ = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_SIZE);
+ static const svn_string_t str_has_props
+ = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_HAS_PROPS);
+ static const svn_string_t str_created_rev
+ = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_CREATED_REV);
+ static const svn_string_t str_time
+ = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_TIME);
+ static const svn_string_t str_last_author
+ = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_LAST_AUTHOR);
+
server_baton_t *b = baton;
const char *path, *full_path;
svn_revnum_t rev;
@@ -1651,15 +1706,15 @@ static svn_error_t *get_dir(svn_ra_svn_c
svn_boolean_t want_props, want_contents;
apr_uint64_t wants_inherited_props;
apr_uint64_t dirent_fields;
- apr_array_header_t *dirent_fields_list = NULL;
- svn_ra_svn_item_t *elt;
+ svn_ra_svn__list_t *dirent_fields_list = NULL;
+ svn_ra_svn__item_t *elt;
int i;
authz_baton_t ab;
ab.server = b;
ab.conn = conn;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)bb?l?B", &path, &rev,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)bb?l?B", &path, &rev,
&want_props, &want_contents,
&dirent_fields_list,
&wants_inherited_props));
@@ -1677,23 +1732,23 @@ static svn_error_t *get_dir(svn_ra_svn_c
for (i = 0; i < dirent_fields_list->nelts; ++i)
{
- elt = &APR_ARRAY_IDX(dirent_fields_list, i, svn_ra_svn_item_t);
+ elt = &SVN_RA_SVN__LIST_ITEM(dirent_fields_list, i);
if (elt->kind != SVN_RA_SVN_WORD)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
"Dirent field not a string");
- if (strcmp(SVN_RA_SVN_DIRENT_KIND, elt->u.word) == 0)
+ if (svn_string_compare(&str_kind, &elt->u.word))
dirent_fields |= SVN_DIRENT_KIND;
- else if (strcmp(SVN_RA_SVN_DIRENT_SIZE, elt->u.word) == 0)
+ else if (svn_string_compare(&str_size, &elt->u.word))
dirent_fields |= SVN_DIRENT_SIZE;
- else if (strcmp(SVN_RA_SVN_DIRENT_HAS_PROPS, elt->u.word) == 0)
+ else if (svn_string_compare(&str_has_props, &elt->u.word))
dirent_fields |= SVN_DIRENT_HAS_PROPS;
- else if (strcmp(SVN_RA_SVN_DIRENT_CREATED_REV, elt->u.word) == 0)
+ else if (svn_string_compare(&str_created_rev, &elt->u.word))
dirent_fields |= SVN_DIRENT_CREATED_REV;
- else if (strcmp(SVN_RA_SVN_DIRENT_TIME, elt->u.word) == 0)
+ else if (svn_string_compare(&str_time, &elt->u.word))
dirent_fields |= SVN_DIRENT_TIME;
- else if (strcmp(SVN_RA_SVN_DIRENT_LAST_AUTHOR, elt->u.word) == 0)
+ else if (svn_string_compare(&str_last_author, &elt->u.word))
dirent_fields |= SVN_DIRENT_LAST_AUTHOR;
}
}
@@ -1779,12 +1834,9 @@ static svn_error_t *get_dir(svn_ra_svn_c
if (dirent_fields & SVN_DIRENT_HAS_PROPS)
{
- apr_hash_t *file_props;
-
/* has_props */
- SVN_CMD_ERR(svn_fs_node_proplist(&file_props, root, file_path,
+ SVN_CMD_ERR(svn_fs_node_has_props(&has_props, root, file_path,
subpool));
- has_props = (apr_hash_count(file_props) > 0);
}
if ((dirent_fields & SVN_DIRENT_LAST_AUTHOR)
@@ -1841,8 +1893,11 @@ static svn_error_t *get_dir(svn_ra_svn_c
return svn_ra_svn__write_tuple(conn, pool, "!))");
}
-static svn_error_t *update(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+update(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -1856,7 +1911,7 @@ static svn_error_t *update(svn_ra_svn_co
svn_boolean_t is_checkout;
/* Parse the arguments. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)cb?w3?3", &rev, &target,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cb?w3?3", &rev, &target,
&recurse, &depth_word,
&send_copyfrom_args, &ignore_ancestry));
target = svn_relpath_canonicalize(target, pool);
@@ -1896,8 +1951,11 @@ static svn_error_t *update(svn_ra_svn_co
return SVN_NO_ERROR;
}
-static svn_error_t *switch_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+switch_cmd(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -1911,7 +1969,7 @@ static svn_error_t *switch_cmd(svn_ra_sv
svn_tristate_t ignore_ancestry; /* Optional; default TRUE */
/* Parse the arguments. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)cbc?w?33", &rev, &target,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cbc?w?33", &rev, &target,
&recurse, &switch_url, &depth_word,
&send_copyfrom_args, &ignore_ancestry));
target = svn_relpath_canonicalize(target, pool);
@@ -1946,8 +2004,11 @@ static svn_error_t *switch_cmd(svn_ra_sv
(ignore_ancestry != svn_tristate_false));
}
-static svn_error_t *status(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+status(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -1958,7 +2019,7 @@ static svn_error_t *status(svn_ra_svn_co
svn_depth_t depth = svn_depth_unknown;
/* Parse the arguments. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cb?(?r)?w",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "cb?(?r)?w",
&target, &recurse, &rev, &depth_word));
target = svn_relpath_canonicalize(target, pool);
@@ -1982,8 +2043,11 @@ static svn_error_t *status(svn_ra_svn_co
depth, FALSE, FALSE);
}
-static svn_error_t *diff(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+diff(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -1998,14 +2062,14 @@ static svn_error_t *diff(svn_ra_svn_conn
if (params->nelts == 5)
{
/* Clients before 1.4 don't send the text_deltas boolean or depth. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)cbbc", &rev, &target,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cbbc", &rev, &target,
&recurse, &ignore_ancestry, &versus_url));
text_deltas = TRUE;
depth_word = NULL;
}
else
{
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)cbbcb?w",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cbbcb?w",
&rev, &target, &recurse,
&ignore_ancestry, &versus_url,
&text_deltas, &depth_word));
@@ -2048,12 +2112,16 @@ static svn_error_t *diff(svn_ra_svn_conn
ASSUMPTION: When performing a 'merge' with two URLs at different
revisions, the client will call this command more than once. */
-static svn_error_t *get_mergeinfo(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+get_mergeinfo(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
- apr_array_header_t *paths, *canonical_paths;
+ svn_ra_svn__list_t *paths;
+ apr_array_header_t *canonical_paths;
svn_mergeinfo_catalog_t mergeinfo;
int i;
apr_hash_index_t *hi;
@@ -2066,7 +2134,7 @@ static svn_error_t *get_mergeinfo(svn_ra
ab.server = b;
ab.conn = conn;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "l(?r)wb", &paths, &rev,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "l(?r)wb", &paths, &rev,
&inherit_word, &include_descendants));
inherit = svn_inheritance_from_word(inherit_word);
@@ -2074,13 +2142,13 @@ static svn_error_t *get_mergeinfo(svn_ra
canonical_paths = apr_array_make(pool, paths->nelts, sizeof(const char *));
for (i = 0; i < paths->nelts; i++)
{
- svn_ra_svn_item_t *item = &APR_ARRAY_IDX(paths, i, svn_ra_svn_item_t);
+ svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(paths, i);
const char *full_path;
if (item->kind != SVN_RA_SVN_STRING)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Path is not a string"));
- full_path = svn_relpath_canonicalize(item->u.string->data, pool);
+ full_path = svn_relpath_canonicalize(item->u.string.data, pool);
full_path = svn_fspath__join(b->repository->fs_path->data, full_path, pool);
APR_ARRAY_PUSH(canonical_paths, const char *) = full_path;
}
@@ -2203,17 +2271,21 @@ static svn_error_t *log_receiver(void *b
return SVN_NO_ERROR;
}
-static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+log_cmd(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
svn_error_t *err, *write_err;
server_baton_t *b = baton;
svn_revnum_t start_rev, end_rev;
const char *full_path;
svn_boolean_t send_changed_paths, strict_node, include_merged_revisions;
- apr_array_header_t *paths, *full_paths, *revprop_items, *revprops;
+ apr_array_header_t *full_paths, *revprops;
+ svn_ra_svn__list_t *paths, *revprop_items;
char *revprop_word;
- svn_ra_svn_item_t *elt;
+ svn_ra_svn__item_t *elt;
int i;
apr_uint64_t limit, include_merged_revs_param;
log_baton_t lb;
@@ -2222,7 +2294,7 @@ static svn_error_t *log_cmd(svn_ra_svn_c
ab.server = b;
ab.conn = conn;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "l(?r)(?r)bb?n?Bwl", &paths,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "l(?r)(?r)bb?n?Bwl", &paths,
&start_rev, &end_rev, &send_changed_paths,
&strict_node, &limit,
&include_merged_revs_param,
@@ -2246,11 +2318,11 @@ static svn_error_t *log_cmd(svn_ra_svn_c
sizeof(char *));
for (i = 0; i < revprop_items->nelts; i++)
{
- elt = &APR_ARRAY_IDX(revprop_items, i, svn_ra_svn_item_t);
+ elt = &SVN_RA_SVN__LIST_ITEM(revprop_items, i);
if (elt->kind != SVN_RA_SVN_STRING)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Log revprop entry not a string"));
- APR_ARRAY_PUSH(revprops, const char *) = elt->u.string->data;
+ APR_ARRAY_PUSH(revprops, const char *) = elt->u.string.data;
}
}
else
@@ -2268,11 +2340,11 @@ static svn_error_t *log_cmd(svn_ra_svn_c
full_paths = apr_array_make(pool, paths->nelts, sizeof(const char *));
for (i = 0; i < paths->nelts; i++)
{
- elt = &APR_ARRAY_IDX(paths, i, svn_ra_svn_item_t);
+ elt = &SVN_RA_SVN__LIST_ITEM(paths, i);
if (elt->kind != SVN_RA_SVN_STRING)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Log path entry not a string"));
- full_path = svn_relpath_canonicalize(elt->u.string->data, pool),
+ full_path = svn_relpath_canonicalize(elt->u.string.data, pool),
full_path = svn_fspath__join(b->repository->fs_path->data, full_path,
pool);
APR_ARRAY_PUSH(full_paths, const char *) = full_path;
@@ -2306,8 +2378,11 @@ static svn_error_t *log_cmd(svn_ra_svn_c
return SVN_NO_ERROR;
}
-static svn_error_t *check_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+check_path(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -2315,7 +2390,7 @@ static svn_error_t *check_path(svn_ra_sv
svn_fs_root_t *root;
svn_node_kind_t kind;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)", &path, &rev));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev));
full_path = svn_fspath__join(b->repository->fs_path->data,
svn_relpath_canonicalize(path, pool), pool);
@@ -2336,8 +2411,11 @@ static svn_error_t *check_path(svn_ra_sv
return SVN_NO_ERROR;
}
-static svn_error_t *stat_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+stat_cmd(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
@@ -2345,7 +2423,7 @@ static svn_error_t *stat_cmd(svn_ra_svn_
svn_fs_root_t *root;
svn_dirent_t *dirent;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)", &path, &rev));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev));
full_path = svn_fspath__join(b->repository->fs_path->data,
svn_relpath_canonicalize(path, pool), pool);
@@ -2383,14 +2461,18 @@ static svn_error_t *stat_cmd(svn_ra_svn_
return SVN_NO_ERROR;
}
-static svn_error_t *get_locations(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+get_locations(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
svn_error_t *err, *write_err;
server_baton_t *b = baton;
svn_revnum_t revision;
- apr_array_header_t *location_revisions, *loc_revs_proto;
- svn_ra_svn_item_t *elt;
+ apr_array_header_t *location_revisions;
+ svn_ra_svn__list_t *loc_revs_proto;
+ svn_ra_svn__item_t *elt;
int i;
const char *relative_path;
svn_revnum_t peg_revision;
@@ -2402,7 +2484,7 @@ static svn_error_t *get_locations(svn_ra
ab.conn = conn;
/* Parse the arguments. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "crl", &relative_path,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "crl", &relative_path,
&peg_revision,
&loc_revs_proto));
relative_path = svn_relpath_canonicalize(relative_path, pool);
@@ -2414,7 +2496,7 @@ static svn_error_t *get_locations(svn_ra
sizeof(svn_revnum_t));
for (i = 0; i < loc_revs_proto->nelts; i++)
{
- elt = &APR_ARRAY_IDX(loc_revs_proto, i, svn_ra_svn_item_t);
+ elt = &SVN_RA_SVN__LIST_ITEM(loc_revs_proto, i);
if (elt->kind != SVN_RA_SVN_NUMBER)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
"Get-locations location revisions entry "
@@ -2482,10 +2564,11 @@ static svn_error_t *gls_receiver(svn_loc
segment->path);
}
-static svn_error_t *get_location_segments(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- apr_array_header_t *params,
- void *baton)
+static svn_error_t *
+get_location_segments(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
svn_error_t *err, *write_err;
server_baton_t *b = baton;
@@ -2498,7 +2581,7 @@ static svn_error_t *get_location_segment
ab.conn = conn;
/* Parse the arguments. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)(?r)(?r)",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)(?r)(?r)",
&relative_path, &peg_revision,
&start_rev, &end_rev));
relative_path = svn_relpath_canonicalize(relative_path, pool);
@@ -2506,32 +2589,56 @@ static svn_error_t *get_location_segment
abs_path = svn_fspath__join(b->repository->fs_path->data, relative_path,
pool);
- if (SVN_IS_VALID_REVNUM(start_rev)
- && SVN_IS_VALID_REVNUM(end_rev)
- && (end_rev > start_rev))
+ SVN_ERR(trivial_auth_request(conn, pool, b));
+ SVN_ERR(log_command(baton, conn, pool, "%s",
+ svn_log__get_location_segments(abs_path, peg_revision,
+ start_rev, end_rev,
+ pool)));
+
+ /* No START_REV or PEG_REVISION? We'll use HEAD. */
+ if (!SVN_IS_VALID_REVNUM(start_rev) || !SVN_IS_VALID_REVNUM(peg_revision))
{
- err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+ svn_revnum_t youngest;
+
+ err = svn_fs_youngest_rev(&youngest, b->repository->fs, pool);
+
+ if (err)
+ {
+ err = svn_error_compose_create(
+ svn_ra_svn__write_word(conn, pool, "done"),
+ err);
+
+ return log_fail_and_flush(err, b, conn, pool);
+ }
+
+ if (!SVN_IS_VALID_REVNUM(start_rev))
+ start_rev = youngest;
+ if (!SVN_IS_VALID_REVNUM(peg_revision))
+ peg_revision = youngest;
+ }
+
+ /* No END_REV? We'll use 0. */
+ if (!SVN_IS_VALID_REVNUM(end_rev))
+ end_rev = 0;
+
+ if (end_rev > start_rev)
+ {
+ err = svn_ra_svn__write_word(conn, pool, "done");
+ err = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, err,
"Get-location-segments end revision must not be "
"younger than start revision");
return log_fail_and_flush(err, b, conn, pool);
}
- if (SVN_IS_VALID_REVNUM(peg_revision)
- && SVN_IS_VALID_REVNUM(start_rev)
- && (start_rev > peg_revision))
+ if (start_rev > peg_revision)
{
- err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+ err = svn_ra_svn__write_word(conn, pool, "done");
+ err = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, err,
"Get-location-segments start revision must not "
"be younger than peg revision");
return log_fail_and_flush(err, b, conn, pool);
}
- SVN_ERR(trivial_auth_request(conn, pool, b));
- SVN_ERR(log_command(baton, conn, pool, "%s",
- svn_log__get_location_segments(abs_path, peg_revision,
- start_rev, end_rev,
- pool)));
-
/* All the parameters are fine - let's perform the query against the
* repository. */
@@ -2546,8 +2653,7 @@ static svn_error_t *get_location_segment
write_err = svn_ra_svn__write_word(conn, pool, "done");
if (write_err)
{
- svn_error_clear(err);
- return write_err;
+ return svn_error_compose_create(write_err, err);
}
SVN_CMD_ERR(err);
@@ -2624,8 +2730,11 @@ static svn_error_t *file_rev_handler(voi
return SVN_NO_ERROR;
}
-static svn_error_t *get_file_revs(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+get_file_revs(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_error_t *err, *write_err;
@@ -2641,7 +2750,7 @@ static svn_error_t *get_file_revs(svn_ra
ab.conn = conn;
/* Parse arguments. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)(?r)?B",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)(?r)?B",
&path, &start_rev, &end_rev,
&include_merged_revs_param));
path = svn_relpath_canonicalize(path, pool);
@@ -2677,8 +2786,11 @@ static svn_error_t *get_file_revs(svn_ra
return SVN_NO_ERROR;
}
-static svn_error_t *lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+lock(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
const char *path;
@@ -2688,7 +2800,7 @@ static svn_error_t *lock(svn_ra_svn_conn
svn_revnum_t current_rev;
svn_lock_t *l;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?c)b(?r)", &path, &comment,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?c)b(?r)", &path, &comment,
&steal_lock, ¤t_rev));
full_path = svn_fspath__join(b->repository->fs_path->data,
svn_relpath_canonicalize(path, pool), pool);
@@ -2751,11 +2863,14 @@ clear_lock_result_hash(apr_hash_t *resul
}
}
-static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+lock_many(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
- apr_array_header_t *path_revs;
+ svn_ra_svn__list_t *path_revs;
const char *comment;
svn_boolean_t steal_lock;
int i;
@@ -2766,7 +2881,7 @@ static svn_error_t *lock_many(svn_ra_svn
apr_hash_index_t *hi;
struct lock_many_baton_t lmb;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?c)bl", &comment, &steal_lock,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "(?c)bl", &comment, &steal_lock,
&path_revs));
subpool = svn_pool_create(pool);
@@ -2782,8 +2897,7 @@ static svn_error_t *lock_many(svn_ra_svn
{
const char *path, *full_path;
svn_revnum_t current_rev;
- svn_ra_svn_item_t *item = &APR_ARRAY_IDX(path_revs, i,
- svn_ra_svn_item_t);
+ svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(path_revs, i);
svn_fs_lock_target_t *target;
svn_pool_clear(subpool);
@@ -2792,7 +2906,7 @@ static svn_error_t *lock_many(svn_ra_svn
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
"Lock requests should be list of lists");
- SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, subpool, "c(?r)", &path,
+ SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "c(?r)", &path,
¤t_rev));
full_path = svn_fspath__join(b->repository->fs_path->data,
@@ -2846,14 +2960,13 @@ static svn_error_t *lock_many(svn_ra_svn
{
const char *path, *full_path;
svn_revnum_t current_rev;
- svn_ra_svn_item_t *item = &APR_ARRAY_IDX(path_revs, i,
- svn_ra_svn_item_t);
+ svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(path_revs, i);
struct lock_result_t *result;
svn_pool_clear(subpool);
- write_err = svn_ra_svn__parse_tuple(item->u.list, subpool, "c(?r)", &path,
- ¤t_rev);
+ write_err = svn_ra_svn__parse_tuple(&item->u.list, "c(?r)",
+ &path, ¤t_rev);
if (write_err)
break;
@@ -2907,14 +3020,17 @@ static svn_error_t *lock_many(svn_ra_svn
return SVN_NO_ERROR;
}
-static svn_error_t *unlock(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+unlock(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
const char *path, *token, *full_path;
svn_boolean_t break_lock;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?c)b", &path, &token,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?c)b", &path, &token,
&break_lock));
full_path = svn_fspath__join(b->repository->fs_path->data,
@@ -2934,12 +3050,15 @@ static svn_error_t *unlock(svn_ra_svn_co
return SVN_NO_ERROR;
}
-static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+unlock_many(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
svn_boolean_t break_lock;
- apr_array_header_t *unlock_tokens;
+ svn_ra_svn__list_t *unlock_tokens;
int i;
apr_pool_t *subpool;
svn_error_t *err = SVN_NO_ERROR, *write_err = SVN_NO_ERROR;
@@ -2948,8 +3067,7 @@ static svn_error_t *unlock_many(svn_ra_s
apr_hash_index_t *hi;
struct lock_many_baton_t lmb;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "bl", &break_lock,
- &unlock_tokens));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "bl", &break_lock, &unlock_tokens));
/* Username required unless break_lock was specified. */
SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, NULL, ! break_lock));
@@ -2959,8 +3077,7 @@ static svn_error_t *unlock_many(svn_ra_s
/* Parse the unlock requests from PATH_REVS into TARGETS. */
for (i = 0; i < unlock_tokens->nelts; i++)
{
- svn_ra_svn_item_t *item = &APR_ARRAY_IDX(unlock_tokens, i,
- svn_ra_svn_item_t);
+ svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(unlock_tokens, i);
const char *path, *full_path, *token;
svn_pool_clear(subpool);
@@ -2969,7 +3086,7 @@ static svn_error_t *unlock_many(svn_ra_s
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
"Unlock request should be a list of lists");
- SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, subpool, "c(?c)", &path,
+ SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "c(?c)", &path,
&token));
if (!token)
token = "";
@@ -3022,14 +3139,13 @@ static svn_error_t *unlock_many(svn_ra_s
for (i = 0; i < unlock_tokens->nelts; ++i)
{
const char *path, *token, *full_path;
- svn_ra_svn_item_t *item = &APR_ARRAY_IDX(unlock_tokens, i,
- svn_ra_svn_item_t);
+ svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(unlock_tokens, i);
struct lock_result_t *result;
svn_pool_clear(subpool);
- write_err = svn_ra_svn__parse_tuple(item->u.list, subpool, "c(?c)", &path,
- &token);
+ write_err = svn_ra_svn__parse_tuple(&item->u.list, "c(?c)",
+ &path, &token);
if (write_err)
break;
@@ -3076,15 +3192,18 @@ static svn_error_t *unlock_many(svn_ra_s
return SVN_NO_ERROR;
}
-static svn_error_t *get_lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+get_lock(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
const char *path;
const char *full_path;
svn_lock_t *l;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &path));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &path));
full_path = svn_fspath__join(b->repository->fs_path->data,
svn_relpath_canonicalize(path, pool), pool);
@@ -3104,8 +3223,11 @@ static svn_error_t *get_lock(svn_ra_svn_
return SVN_NO_ERROR;
}
-static svn_error_t *get_locks(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+get_locks(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
server_baton_t *b = baton;
const char *path;
@@ -3120,7 +3242,7 @@ static svn_error_t *get_locks(svn_ra_svn
ab.server = b;
ab.conn = conn;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c?(?w)", &path, &depth_word));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c?(?w)", &path, &depth_word));
depth = depth_word ? svn_depth_from_word(depth_word) : svn_depth_infinity;
if ((depth != svn_depth_empty) &&
@@ -3193,14 +3315,17 @@ static svn_error_t *replay_one_revision(
return svn_ra_svn__write_cmd_finish_replay(conn, pool);
}
-static svn_error_t *replay(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+replay(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
svn_revnum_t rev, low_water_mark;
svn_boolean_t send_deltas;
server_baton_t *b = baton;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rrb", &rev, &low_water_mark,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "rrb", &rev, &low_water_mark,
&send_deltas));
SVN_ERR(trivial_auth_request(conn, pool, b));
@@ -3213,8 +3338,11 @@ static svn_error_t *replay(svn_ra_svn_co
return SVN_NO_ERROR;
}
-static svn_error_t *replay_range(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- apr_array_header_t *params, void *baton)
+static svn_error_t *
+replay_range(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
{
svn_revnum_t start_rev, end_rev, rev, low_water_mark;
svn_boolean_t send_deltas;
@@ -3225,7 +3353,7 @@ static svn_error_t *replay_range(svn_ra_
ab.server = b;
ab.conn = conn;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rrrb", &start_rev,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "rrrb", &start_rev,
&end_rev, &low_water_mark,
&send_deltas));
@@ -3261,7 +3389,7 @@ static svn_error_t *replay_range(svn_ra_
static svn_error_t *
get_deleted_rev(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- apr_array_header_t *params,
+ svn_ra_svn__list_t *params,
void *baton)
{
server_baton_t *b = baton;
@@ -3270,7 +3398,7 @@ get_deleted_rev(svn_ra_svn_conn_t *conn,
svn_revnum_t end_revision;
svn_revnum_t revision_deleted;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "crr",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "crr",
&path, &peg_revision, &end_revision));
full_path = svn_fspath__join(b->repository->fs_path->data,
svn_relpath_canonicalize(path, pool), pool);
@@ -3285,7 +3413,7 @@ get_deleted_rev(svn_ra_svn_conn_t *conn,
static svn_error_t *
get_inherited_props(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- apr_array_header_t *params,
+ svn_ra_svn__list_t *params,
void *baton)
{
server_baton_t *b = baton;
@@ -3296,12 +3424,13 @@ get_inherited_props(svn_ra_svn_conn_t *c
int i;
apr_pool_t *iterpool = svn_pool_create(pool);
authz_baton_t ab;
+ svn_node_kind_t node_kind;
ab.server = b;
ab.conn = conn;
/* Parse arguments. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, iterpool, "c(?r)", &path, &rev));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev));
full_path = svn_fspath__join(b->repository->fs_path->data,
svn_relpath_canonicalize(path, iterpool),
@@ -3311,15 +3440,18 @@ get_inherited_props(svn_ra_svn_conn_t *c
SVN_ERR(must_have_access(conn, iterpool, b, svn_authz_read,
full_path, FALSE));
- if (!SVN_IS_VALID_REVNUM(rev))
- SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->repository->fs, pool));
-
SVN_ERR(log_command(b, conn, pool, "%s",
svn_log__get_inherited_props(full_path, rev,
iterpool)));
/* Fetch the properties and a stream for the contents. */
SVN_CMD_ERR(svn_fs_revision_root(&root, b->repository->fs, rev, iterpool));
+ SVN_CMD_ERR(svn_fs_check_path(&node_kind, root, full_path, pool));
+ if (node_kind == svn_node_none)
+ {
+ SVN_CMD_ERR(svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
+ _("'%s' path not found"), full_path));
+ }
SVN_CMD_ERR(get_props(NULL, &inherited_props, &ab, root, full_path, pool));
/* Send successful command response with revision and props. */
@@ -3345,7 +3477,7 @@ get_inherited_props(svn_ra_svn_conn_t *c
return SVN_NO_ERROR;
}
-static const svn_ra_svn_cmd_entry_t main_commands[] = {
+static const svn_ra_svn__cmd_entry_t main_commands[] = {
{ "reparent", reparent },
{ "get-latest-rev", get_latest_rev },
{ "get-dated-rev", get_dated_rev },
@@ -3750,7 +3882,7 @@ construct_server_baton(server_baton_t **
svn_error_t *err, *io_err;
apr_uint64_t ver;
const char *client_url, *ra_client_string, *client_string;
- apr_array_header_t *caplist;
+ svn_ra_svn__list_t *caplist;
apr_pool_t *conn_pool = svn_ra_svn__get_pool(conn);
server_baton_t *b = apr_pcalloc(conn_pool, sizeof(*b));
fs_warning_baton_t *warn_baton;
@@ -3816,7 +3948,7 @@ construct_server_baton(server_baton_t **
return SVN_NO_ERROR;
client_url = svn_uri_canonicalize(client_url, conn_pool);
- SVN_ERR(svn_ra_svn_set_capabilities(conn, caplist));
+ SVN_ERR(svn_ra_svn__set_capabilities(conn, caplist));
/* All released versions of Subversion support edit-pipeline,
* so we do not accept connections from clients that do not. */
@@ -3827,22 +3959,25 @@ construct_server_baton(server_baton_t **
they get handed to the start-commit hook). While we could add a
new interface to re-retrieve them from conn and convert the
result to a list, it's simpler to just convert caplist by hand
- here, since we already have it and turning 'svn_ra_svn_item_t's
+ here, since we already have it and turning 'svn_ra_svn__item_t's
into 'const char *'s is pretty easy.
We only record capabilities we care about. The client may report
more (because it doesn't know what the server cares about). */
{
int i;
- svn_ra_svn_item_t *item;
+ svn_ra_svn__item_t *item;
b->repository->capabilities = apr_array_make(conn_pool, 1,
sizeof(const char *));
for (i = 0; i < caplist->nelts; i++)
{
- item = &APR_ARRAY_IDX(caplist, i, svn_ra_svn_item_t);
+ static const svn_string_t str_cap_mergeinfo
+ = SVN__STATIC_STRING(SVN_RA_SVN_CAP_MERGEINFO);
+
+ item = &SVN_RA_SVN__LIST_ITEM(caplist, i);
/* ra_svn_set_capabilities() already type-checked for us */
- if (strcmp(item->u.word, SVN_RA_SVN_CAP_MERGEINFO) == 0)
+ if (svn_string_compare(&item->u.word, &str_cap_mergeinfo))
{
APR_ARRAY_PUSH(b->repository->capabilities, const char *)
= SVN_RA_CAPABILITY_MERGEINFO;
@@ -3850,7 +3985,7 @@ construct_server_baton(server_baton_t **
/* Save for operational log. */
if (cap_log->len > 0)
svn_stringbuf_appendcstr(cap_log, " ");
- svn_stringbuf_appendcstr(cap_log, item->u.word);
+ svn_stringbuf_appendcstr(cap_log, item->u.word.data);
}
}
@@ -3959,7 +4094,7 @@ serve_interruptable(svn_boolean_t *termi
{
svn_boolean_t terminate = FALSE;
svn_error_t *err = NULL;
- const svn_ra_svn_cmd_entry_t *command;
+ const svn_ra_svn__cmd_entry_t *command;
apr_pool_t *iterpool = svn_pool_create(pool);
/* Prepare command parser. */
@@ -3988,10 +4123,12 @@ serve_interruptable(svn_boolean_t *termi
/* create the connection, configure ports etc. */
connection->conn
- = svn_ra_svn_create_conn4(connection->usock, NULL, NULL,
+ = svn_ra_svn_create_conn5(connection->usock, NULL, NULL,
connection->params->compression_level,
connection->params->zero_copy_limit,
connection->params->error_check_interval,
+ connection->params->max_request_size,
+ connection->params->max_response_size,
connection->pool);
/* Construct server baton and open the repository for the first time. */
Modified: subversion/branches/ra-git/subversion/svnserve/server.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnserve/server.h?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnserve/server.h (original)
+++ subversion/branches/ra-git/subversion/svnserve/server.h Mon Nov 30 10:24:16 2015
@@ -152,6 +152,12 @@ typedef struct serve_params_t {
coming in from the client. */
apr_size_t error_check_interval;
+ /* If not 0, error out on requests exceeding this value. */
+ apr_uint64_t max_request_size;
+
+ /* If not 0, stop sending a response once it exceeds this value. */
+ apr_uint64_t max_response_size;
+
/* Use virtual-host-based path to repo. */
svn_boolean_t vhost;
} serve_params_t;
Modified: subversion/branches/ra-git/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnserve/svnserve.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnserve/svnserve.c (original)
+++ subversion/branches/ra-git/subversion/svnserve/svnserve.c Mon Nov 30 10:24:16 2015
@@ -155,6 +155,15 @@ enum run_mode {
*/
#define ACCEPT_BACKLOG 128
+/* Default limit to the client request size in MBytes. This effectively
+ * limits the size of a paths and individual property values to about
+ * this value.
+ *
+ * Note that (MAX_REQUEST_SIZE + 4M) * THREADPOOL_MAX_SIZE is roughly
+ * the peak memory usage of the RA layer.
+ */
+#define MAX_REQUEST_SIZE 16
+
#ifdef WIN32
static apr_os_sock_t winservice_svnserve_accept_socket = INVALID_SOCKET;
@@ -210,6 +219,19 @@ void winservice_notify_stop(void)
#define SVNSERVE_OPT_MIN_THREADS 271
#define SVNSERVE_OPT_MAX_THREADS 272
#define SVNSERVE_OPT_BLOCK_READ 273
+#define SVNSERVE_OPT_MAX_REQUEST 274
+#define SVNSERVE_OPT_MAX_RESPONSE 275
+
+/* Text macro because we can't use #ifdef sections inside a N_("...")
+ macro expansion. */
+#ifdef CONNECTION_HAVE_THREAD_OPTION
+#define ONLY_AVAILABLE_WITH_THEADS \
+ "\n" \
+ " "\
+ "[used only with --threads]"
+#else
+#define ONLY_AVAILABLE_WITH_THEADS ""
+#endif
static const apr_getopt_option_t svnserve__options[] =
{
@@ -317,34 +339,46 @@ static const apr_getopt_option_t svnserv
* ### this option never exists when --service exists. */
{"threads", 'T', 0, N_("use threads instead of fork "
"[mode: daemon]")},
+#endif
+#if APR_HAS_THREADS
{"min-threads", SVNSERVE_OPT_MIN_THREADS, 1,
N_("Minimum number of server threads, even if idle.\n"
" "
- "Caped to max-threads; minimum value is 0.\n"
- " "
- "Default is 1.\n"
+ "Capped to max-threads; minimum value is 0.\n"
" "
- "[used only with --threads]")},
-#if (APR_SIZEOF_VOIDP <= 4)
+ "Default is 1."
+ ONLY_AVAILABLE_WITH_THEADS)},
{"max-threads", SVNSERVE_OPT_MAX_THREADS, 1,
N_("Maximum number of server threads, even if there\n"
" "
"are more connections. Minimum value is 1.\n"
" "
- "Default is 64.\n"
+ "Default is " APR_STRINGIFY(THREADPOOL_MAX_SIZE) "."
+ ONLY_AVAILABLE_WITH_THEADS)},
+#endif
+ {"max-request-size", SVNSERVE_OPT_MAX_REQUEST, 1,
+ N_("Maximum acceptable size of a client request in MB.\n"
" "
- "[used only with --threads]")},
-#else
- {"max-threads", SVNSERVE_OPT_MAX_THREADS, 1,
- N_("Maximum number of server threads, even if there\n"
+ "This implicitly limits the length of paths and\n"
" "
- "are more connections. Minimum value is 1.\n"
+ "property values that can be sent to the server.\n"
" "
- "Default is 256.\n"
+ "Also the peak memory usage for protocol handling\n"
" "
- "[used only with --threads]")},
-#endif
-#endif
+ "per server thread or sub-process.\n"
+ " "
+ "0 disables the size check; default is "
+ APR_STRINGIFY(MAX_REQUEST_SIZE) ".")},
+ {"max-response-size", SVNSERVE_OPT_MAX_RESPONSE, 1,
+ N_("Maximum acceptable server response size in MB.\n"
+ " "
+ "Longer responses get truncated and return an\n"
+ " "
+ "error. This limits the server load e.g. when\n"
+ " "
+ "checking out at the wrong path level.\n"
+ " "
+ "Default is 0 (disabled).")},
{"foreground", SVNSERVE_OPT_FOREGROUND, 0,
N_("run in foreground (useful for debugging)\n"
" "
@@ -728,6 +762,8 @@ sub_main(int *exit_code, int argc, const
params.memory_cache_size = (apr_uint64_t)-1;
params.zero_copy_limit = 0;
params.error_check_interval = 4096;
+ params.max_request_size = MAX_REQUEST_SIZE * 0x100000;
+ params.max_response_size = 0;
while (1)
{
@@ -891,6 +927,14 @@ sub_main(int *exit_code, int argc, const
}
break;
+ case SVNSERVE_OPT_MAX_REQUEST:
+ params.max_request_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
+ break;
+
+ case SVNSERVE_OPT_MAX_RESPONSE:
+ params.max_response_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
+ break;
+
case SVNSERVE_OPT_MIN_THREADS:
min_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
break;
@@ -1030,17 +1074,21 @@ sub_main(int *exit_code, int argc, const
apr_pool_cleanup_register(pool, pool, apr_pool_cleanup_null,
redirect_stdout);
- SVN_ERR(svn_stream_for_stdin(&stdin_stream, pool));
+ /* We are an interactive server, i.e. can't use APR buffering on
+ * stdin. */
+ SVN_ERR(svn_stream_for_stdin2(&stdin_stream, FALSE, pool));
SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
/* Use a subpool for the connection to ensure that if SASL is used
* the pool cleanup handlers that call sasl_dispose() (connection_pool)
* and sasl_done() (pool) are run in the right order. See issue #3664. */
connection_pool = svn_pool_create(pool);
- conn = svn_ra_svn_create_conn4(NULL, stdin_stream, stdout_stream,
+ conn = svn_ra_svn_create_conn5(NULL, stdin_stream, stdout_stream,
params.compression_level,
params.zero_copy_limit,
params.error_check_interval,
+ params.max_request_size,
+ params.max_response_size,
connection_pool);
err = serve(conn, ¶ms, connection_pool);
svn_pool_destroy(connection_pool);
Modified: subversion/branches/ra-git/subversion/svnsync/svnsync.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnsync/svnsync.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnsync/svnsync.c (original)
+++ subversion/branches/ra-git/subversion/svnsync/svnsync.c Mon Nov 30 10:24:16 2015
@@ -68,12 +68,10 @@ enum svnsync__opt {
svnsync_opt_disable_locking,
svnsync_opt_version,
svnsync_opt_trust_server_cert,
- svnsync_opt_trust_server_cert_unknown_ca,
- svnsync_opt_trust_server_cert_cn_mismatch,
- svnsync_opt_trust_server_cert_expired,
- svnsync_opt_trust_server_cert_not_yet_valid,
- svnsync_opt_trust_server_cert_other_failure,
+ svnsync_opt_trust_server_cert_failures_src,
+ svnsync_opt_trust_server_cert_failures_dst,
svnsync_opt_allow_non_empty,
+ svnsync_opt_skip_unchanged,
svnsync_opt_steal_lock
};
@@ -83,11 +81,8 @@ enum svnsync__opt {
svnsync_opt_auth_username, \
svnsync_opt_auth_password, \
svnsync_opt_trust_server_cert, \
- svnsync_opt_trust_server_cert_unknown_ca, \
- svnsync_opt_trust_server_cert_cn_mismatch, \
- svnsync_opt_trust_server_cert_expired, \
- svnsync_opt_trust_server_cert_not_yet_valid, \
- svnsync_opt_trust_server_cert_other_failure, \
+ svnsync_opt_trust_server_cert_failures_src, \
+ svnsync_opt_trust_server_cert_failures_dst, \
svnsync_opt_source_username, \
svnsync_opt_source_password, \
svnsync_opt_sync_username, \
@@ -154,9 +149,14 @@ static const svn_opt_subcommand_desc2_t
"if untrusted users/administrators may have write access to the\n"
"DEST_URL repository.\n"
"\n"
+ "Unless you need to trigger the destination repositoy's revprop\n"
+ "change hooks for all revision properties, it is recommended to use\n"
+ "the --skip-unchanged option for best performance.\n"
+ "\n"
"Form 2 is deprecated syntax, equivalent to specifying \"-rREV[:REV2]\".\n"),
{ SVNSYNC_OPTS_DEFAULT, svnsync_opt_source_prop_encoding, 'q', 'r',
- svnsync_opt_disable_locking, svnsync_opt_steal_lock, 'M' } },
+ svnsync_opt_disable_locking, svnsync_opt_steal_lock,
+ svnsync_opt_skip_unchanged, 'M' } },
{ "info", info_cmd, { 0 },
N_("usage: svnsync info DEST_URL\n"
"\n"
@@ -185,6 +185,8 @@ static const apr_getopt_option_t svnsync
" 'HEAD' latest in repository") },
{"allow-non-empty", svnsync_opt_allow_non_empty, 0,
N_("allow a non-empty destination repository") },
+ {"skip-unchanged", svnsync_opt_skip_unchanged, 0,
+ N_("don't copy unchanged revision properties") },
{"non-interactive", svnsync_opt_non_interactive, 0,
N_("do no interactive prompting (default is to prompt\n"
" "
@@ -204,29 +206,37 @@ static const apr_getopt_option_t svnsync
" "
"see --source-password and --sync-password)") },
{"trust-server-cert", svnsync_opt_trust_server_cert, 0,
- N_("deprecated; same as --trust-unknown-ca")},
- {"trust-unknown-ca", svnsync_opt_trust_server_cert_unknown_ca, 0,
- N_("with --non-interactive, accept SSL server\n"
+ N_("deprecated; same as\n"
+ " "
+ "--source-trust-server-cert-failures=unknown-ca\n"
+ " "
+ "--sync-trust-server-cert-failures=unknown-ca")},
+ {"source-trust-server-cert-failures", svnsync_opt_trust_server_cert_failures_src, 1,
+ N_("with --non-interactive, accept SSL\n"
" "
- "certificates from unknown certificate authorities")},
- {"trust-cn-mismatch", svnsync_opt_trust_server_cert_cn_mismatch, 0,
- N_("with --non-interactive, accept SSL server\n"
+ "server certificates with failures.\n"
" "
- "certificates even if the server hostname does not\n"
+ "ARG is a comma-separated list of:\n"
" "
- "match the certificate's common name attribute")},
- {"trust-expired", svnsync_opt_trust_server_cert_expired, 0,
- N_("with --non-interactive, accept expired SSL server\n"
+ "- 'unknown-ca' (Unknown Authority)\n"
" "
- "certificates")},
- {"trust-not-yet-valid", svnsync_opt_trust_server_cert_not_yet_valid, 0,
- N_("with --non-interactive, accept SSL server\n"
+ "- 'cn-mismatch' (Hostname mismatch)\n"
" "
- "certificates from the future")},
- {"trust-other-failure", svnsync_opt_trust_server_cert_other_failure, 0,
- N_("with --non-interactive, accept SSL server\n"
+ "- 'expired' (Expired certificate)\n"
" "
- "certificates with failures other than the above")},
+ "- 'not-yet-valid' (Not yet valid certificate)\n"
+ " "
+ "- 'other' (all other not separately classified\n"
+ " "
+ " certificate errors).\n"
+ " "
+ "Applied to the source URL.")},
+ {"sync-trust-server-cert-failures", svnsync_opt_trust_server_cert_failures_dst, 1,
+ N_("Like\n"
+ " "
+ "--source-trust-server-cert-failures,\n"
+ " "
+ "but applied to the destination URL.")},
{"source-username", svnsync_opt_source_username, 1,
N_("connect to source repository with username ARG") },
{"source-password", svnsync_opt_source_password, 1,
@@ -280,11 +290,13 @@ static const apr_getopt_option_t svnsync
typedef struct opt_baton_t {
svn_boolean_t non_interactive;
- svn_boolean_t trust_server_cert_unknown_ca;
- svn_boolean_t trust_server_cert_cn_mismatch;
- svn_boolean_t trust_server_cert_expired;
- svn_boolean_t trust_server_cert_not_yet_valid;
- svn_boolean_t trust_server_cert_other_failure;
+ struct {
+ svn_boolean_t trust_server_cert_unknown_ca;
+ svn_boolean_t trust_server_cert_cn_mismatch;
+ svn_boolean_t trust_server_cert_expired;
+ svn_boolean_t trust_server_cert_not_yet_valid;
+ svn_boolean_t trust_server_cert_other_failure;
+ } src_trust, dst_trust;
svn_boolean_t no_auth_cache;
svn_auth_baton_t *source_auth_baton;
svn_auth_baton_t *sync_auth_baton;
@@ -299,6 +311,7 @@ typedef struct opt_baton_t {
svn_boolean_t steal_lock;
svn_boolean_t quiet;
svn_boolean_t allow_non_empty;
+ svn_boolean_t skip_unchanged;
svn_boolean_t version;
svn_boolean_t help;
svn_opt_revision_t start_rev;
@@ -418,6 +431,7 @@ typedef struct subcommand_baton_t {
svn_ra_callbacks2_t sync_callbacks;
svn_boolean_t quiet;
svn_boolean_t allow_non_empty;
+ svn_boolean_t skip_unchanged; /* Enable optimization for revprop changes. */
const char *to_url;
/* initialize, synchronize, and copy-revprops only */
@@ -588,6 +602,10 @@ filter_props(int *filtered_count, apr_ha
* and set *FILTERED_COUNT to the number of properties thus omitted.
* REV_PROPS is a hash mapping (char *)propname to (svn_string_t *)propval.
*
+ * If OLD_REV_PROPS is not NULL, skip all properties that did not change.
+ * Note that this implies that hook scripts won't be triggered anymore for
+ * those revprops that did not change.
+ *
* All allocations will be done in a subpool of POOL.
*/
static svn_error_t *
@@ -595,6 +613,7 @@ write_revprops(int *filtered_count,
svn_ra_session_t *session,
svn_revnum_t rev,
apr_hash_t *rev_props,
+ apr_hash_t *old_rev_props,
apr_pool_t *pool)
{
apr_pool_t *subpool = svn_pool_create(pool);
@@ -612,6 +631,17 @@ write_revprops(int *filtered_count,
if (strncmp(propname, SVNSYNC_PROP_PREFIX,
sizeof(SVNSYNC_PROP_PREFIX) - 1) != 0)
{
+ if (old_rev_props)
+ {
+ /* Skip the RA call for any no-op propset. */
+ const svn_string_t *old_value = svn_hash_gets(old_rev_props,
+ propname);
+ if ((!old_value && !propval)
+ || (old_value && propval
+ && svn_string_compare(old_value, propval)))
+ continue;
+ }
+
SVN_ERR(svn_ra_change_rev_prop2(session, rev, propname, NULL,
propval, subpool));
}
@@ -673,6 +703,10 @@ log_properties_normalized(int normalized
* If SYNC is TRUE, then properties on the destination revision that
* do not exist on the source revision will be removed.
*
+ * If SKIP_UNCHANGED is TRUE, skip any no-op revprop changes. This also
+ * prevents hook scripts from firing for those unchanged revprops. Has
+ * no effect if SYNC is FALSE.
+ *
* If QUIET is FALSE, then log_properties_copied() is called to log that
* properties were copied for revision REV.
*
@@ -685,6 +719,7 @@ copy_revprops(svn_ra_session_t *from_ses
svn_ra_session_t *to_session,
svn_revnum_t rev,
svn_boolean_t sync,
+ svn_boolean_t skip_unchanged,
svn_boolean_t quiet,
const char *source_prop_encoding,
int *normalized_count,
@@ -710,7 +745,8 @@ copy_revprops(svn_ra_session_t *from_ses
source_prop_encoding, pool));
/* Copy all but the svn:svnsync properties. */
- SVN_ERR(write_revprops(&filtered_count, to_session, rev, rev_props, pool));
+ SVN_ERR(write_revprops(&filtered_count, to_session, rev, rev_props,
+ skip_unchanged ? existing_props : NULL, pool));
/* Delete those properties that were in TARGET but not in SOURCE */
if (sync)
@@ -746,6 +782,7 @@ make_subcommand_baton(opt_baton_t *opt_b
b->sync_callbacks.open_tmp_file = open_tmp_file;
b->sync_callbacks.auth_baton = opt_baton->sync_auth_baton;
b->quiet = opt_baton->quiet;
+ b->skip_unchanged = opt_baton->skip_unchanged;
b->allow_non_empty = opt_baton->allow_non_empty;
b->to_url = to_url;
b->source_prop_encoding = opt_baton->source_prop_encoding;
@@ -855,9 +892,9 @@ do_initialize(svn_ra_session_t *to_sessi
LATEST is not 0, this really serves merely aesthetic and
informational purposes, keeping the output of this command
consistent while allowing folks to see what the latest revision is. */
- SVN_ERR(copy_revprops(from_session, to_session, latest, FALSE, baton->quiet,
- baton->source_prop_encoding, &normalized_rev_props_count,
- pool));
+ SVN_ERR(copy_revprops(from_session, to_session, latest, FALSE, FALSE,
+ baton->quiet, baton->source_prop_encoding,
+ &normalized_rev_props_count, pool));
SVN_ERR(log_properties_normalized(normalized_rev_props_count, 0, pool));
@@ -1368,7 +1405,7 @@ replay_rev_finished(svn_revnum_t revisio
rb->normalized_rev_props_count += normalized_count;
SVN_ERR(write_revprops(&filtered_count, rb->to_session, revision, filtered,
- subpool));
+ NULL, subpool));
/* Remove all extra properties in TARGET. */
SVN_ERR(remove_props_not_in_source(rb->to_session, revision,
@@ -1474,7 +1511,8 @@ do_synchronize(svn_ra_session_t *to_sess
if (copying > last_merged)
{
SVN_ERR(copy_revprops(from_session, to_session, to_latest, TRUE,
- baton->quiet, baton->source_prop_encoding,
+ baton->skip_unchanged, baton->quiet,
+ baton->source_prop_encoding,
&normalized_rev_props_count, pool));
last_merged = copying;
last_merged_rev = svn_string_create
@@ -1645,7 +1683,8 @@ do_copy_revprops(svn_ra_session_t *to_se
{
int normalized_count;
SVN_ERR(check_cancel(NULL));
- SVN_ERR(copy_revprops(from_session, to_session, i, TRUE, baton->quiet,
+ SVN_ERR(copy_revprops(from_session, to_session, i, TRUE,
+ baton->skip_unchanged, baton->quiet,
baton->source_prop_encoding, &normalized_count,
pool));
normalized_rev_props_count += normalized_count;
@@ -2008,24 +2047,30 @@ sub_main(int *exit_code, int argc, const
break;
case svnsync_opt_trust_server_cert: /* backwards compat */
- case svnsync_opt_trust_server_cert_unknown_ca:
- opt_baton.trust_server_cert_unknown_ca = TRUE;
- break;
-
- case svnsync_opt_trust_server_cert_cn_mismatch:
- opt_baton.trust_server_cert_cn_mismatch = TRUE;
- break;
-
- case svnsync_opt_trust_server_cert_expired:
- opt_baton.trust_server_cert_expired = TRUE;
+ opt_baton.src_trust.trust_server_cert_unknown_ca = TRUE;
+ opt_baton.dst_trust.trust_server_cert_unknown_ca = TRUE;
break;
- case svnsync_opt_trust_server_cert_not_yet_valid:
- opt_baton.trust_server_cert_not_yet_valid = TRUE;
+ case svnsync_opt_trust_server_cert_failures_src:
+ SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
+ SVN_ERR(svn_cmdline__parse_trust_options(
+ &opt_baton.src_trust.trust_server_cert_unknown_ca,
+ &opt_baton.src_trust.trust_server_cert_cn_mismatch,
+ &opt_baton.src_trust.trust_server_cert_expired,
+ &opt_baton.src_trust.trust_server_cert_not_yet_valid,
+ &opt_baton.src_trust.trust_server_cert_other_failure,
+ opt_arg, pool));
break;
- case svnsync_opt_trust_server_cert_other_failure:
- opt_baton.trust_server_cert_other_failure = TRUE;
+ case svnsync_opt_trust_server_cert_failures_dst:
+ SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
+ SVN_ERR(svn_cmdline__parse_trust_options(
+ &opt_baton.dst_trust.trust_server_cert_unknown_ca,
+ &opt_baton.dst_trust.trust_server_cert_cn_mismatch,
+ &opt_baton.dst_trust.trust_server_cert_expired,
+ &opt_baton.dst_trust.trust_server_cert_not_yet_valid,
+ &opt_baton.dst_trust.trust_server_cert_other_failure,
+ opt_arg, pool));
break;
case svnsync_opt_no_auth_cache:
@@ -2073,7 +2118,8 @@ sub_main(int *exit_code, int argc, const
SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
SVN_ERR(svn_cmdline__parse_config_option(config_options,
- opt_arg, pool));
+ opt_arg, "svnsync: ",
+ pool));
break;
case svnsync_opt_source_prop_encoding:
@@ -2097,6 +2143,10 @@ sub_main(int *exit_code, int argc, const
opt_baton.allow_non_empty = TRUE;
break;
+ case svnsync_opt_skip_unchanged:
+ opt_baton.skip_unchanged = TRUE;
+ break;
+
case 'q':
opt_baton.quiet = TRUE;
break;
@@ -2139,6 +2189,7 @@ sub_main(int *exit_code, int argc, const
apr_psprintf(pool,
"config:miscellany:memory-cache-size=%s",
opt_arg),
+ NULL /* won't be used */,
pool));
break;
@@ -2214,25 +2265,20 @@ sub_main(int *exit_code, int argc, const
/* --trust-* can only be used with --non-interactive */
if (!opt_baton.non_interactive)
{
- if (opt_baton.trust_server_cert_unknown_ca)
- return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--trust-unknown-ca requires "
- "--non-interactive"));
- if (opt_baton.trust_server_cert_cn_mismatch)
- return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--trust-cn-mismatch requires "
- "--non-interactive"));
- if (opt_baton.trust_server_cert_expired)
- return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--trust-expired requires "
- "--non-interactive"));
- if (opt_baton.trust_server_cert_not_yet_valid)
- return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--trust-not-yet-valid requires "
- "--non-interactive"));
- if (opt_baton.trust_server_cert_other_failure)
+ if (opt_baton.src_trust.trust_server_cert_unknown_ca
+ || opt_baton.src_trust.trust_server_cert_cn_mismatch
+ || opt_baton.src_trust.trust_server_cert_expired
+ || opt_baton.src_trust.trust_server_cert_not_yet_valid
+ || opt_baton.src_trust.trust_server_cert_other_failure
+ || opt_baton.dst_trust.trust_server_cert_unknown_ca
+ || opt_baton.dst_trust.trust_server_cert_cn_mismatch
+ || opt_baton.dst_trust.trust_server_cert_expired
+ || opt_baton.dst_trust.trust_server_cert_not_yet_valid
+ || opt_baton.dst_trust.trust_server_cert_other_failure)
return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--trust-other-failure requires "
+ _("--source-trust-server-cert-failures "
+ "and "
+ "--sync-trust-server-cert-failures require "
"--non-interactive"));
}
@@ -2352,11 +2398,11 @@ sub_main(int *exit_code, int argc, const
opt_baton.source_password,
opt_baton.config_dir,
opt_baton.no_auth_cache,
- opt_baton.trust_server_cert_unknown_ca,
- opt_baton.trust_server_cert_cn_mismatch,
- opt_baton.trust_server_cert_expired,
- opt_baton.trust_server_cert_not_yet_valid,
- opt_baton.trust_server_cert_other_failure,
+ opt_baton.src_trust.trust_server_cert_unknown_ca,
+ opt_baton.src_trust.trust_server_cert_cn_mismatch,
+ opt_baton.src_trust.trust_server_cert_expired,
+ opt_baton.src_trust.trust_server_cert_not_yet_valid,
+ opt_baton.src_trust.trust_server_cert_other_failure,
config,
check_cancel, NULL,
pool);
@@ -2368,11 +2414,11 @@ sub_main(int *exit_code, int argc, const
opt_baton.sync_password,
opt_baton.config_dir,
opt_baton.no_auth_cache,
- opt_baton.trust_server_cert_unknown_ca,
- opt_baton.trust_server_cert_cn_mismatch,
- opt_baton.trust_server_cert_expired,
- opt_baton.trust_server_cert_not_yet_valid,
- opt_baton.trust_server_cert_other_failure,
+ opt_baton.dst_trust.trust_server_cert_unknown_ca,
+ opt_baton.dst_trust.trust_server_cert_cn_mismatch,
+ opt_baton.dst_trust.trust_server_cert_expired,
+ opt_baton.dst_trust.trust_server_cert_not_yet_valid,
+ opt_baton.dst_trust.trust_server_cert_other_failure,
config,
check_cancel, NULL,
pool);