summaryrefslogtreecommitdiff
path: root/subversion/svnserve/serve.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/svnserve/serve.c')
-rw-r--r--subversion/svnserve/serve.c979
1 files changed, 660 insertions, 319 deletions
diff --git a/subversion/svnserve/serve.c b/subversion/svnserve/serve.c
index 91f1d5af961c6..5192e7c9a66f1 100644
--- a/subversion/svnserve/serve.c
+++ b/subversion/svnserve/serve.c
@@ -87,6 +87,9 @@ typedef struct log_baton_t {
const char *fs_path;
svn_ra_svn_conn_t *conn;
int stack_depth;
+
+ /* Set to TRUE when at least one changed path has been sent. */
+ svn_boolean_t started;
} log_baton_t;
typedef struct file_revs_baton_t {
@@ -223,8 +226,8 @@ load_pwdb_config(repository_t *repository,
pwdb_path = svn_dirent_internal_style(pwdb_path, pool);
pwdb_path = svn_dirent_join(repository->base, pwdb_path, pool);
- err = svn_repos__config_pool_get(&repository->pwdb, NULL, config_pool,
- pwdb_path, TRUE, FALSE,
+ err = svn_repos__config_pool_get(&repository->pwdb, config_pool,
+ pwdb_path, TRUE,
repository->repos, pool);
if (err)
{
@@ -282,8 +285,8 @@ canonicalize_access_file(const char **access_file, repository_t *repository,
return SVN_NO_ERROR;
}
-/* Load the authz database for the listening server through AUTHZ_POOL
- based on the entries in the SERVER struct.
+/* Load the authz database for the listening server based on the entries
+ in the SERVER struct.
SERVER and CONN must not be NULL. The real errors will be logged with
SERVER and CONN but return generic errors to the client. */
@@ -291,7 +294,6 @@ static svn_error_t *
load_authz_config(repository_t *repository,
const char *repos_root,
svn_config_t *cfg,
- svn_repos__authz_pool_t *authz_pool,
apr_pool_t *pool)
{
const char *authzdb_path;
@@ -319,9 +321,9 @@ load_authz_config(repository_t *repository,
repos_root, pool);
if (!err)
- err = svn_repos__authz_pool_get(&repository->authzdb, authz_pool,
- authzdb_path, groupsdb_path, TRUE,
- repository->repos, pool);
+ err = svn_repos_authz_read3(&repository->authzdb, authzdb_path,
+ groupsdb_path, TRUE, repository->repos,
+ pool, pool);
if (err)
return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, err, NULL);
@@ -443,7 +445,7 @@ static svn_error_t *authz_check_access(svn_boolean_t *allowed,
absolute path. Passing such a malformed path to the authz
routines throws them into an infinite loop and makes them miss
ACLs. */
- if (path)
+ if (path && *path != '/')
path = svn_fspath__canonicalize(path, pool);
/* If we have a username, and we've not yet used it + any username
@@ -627,11 +629,12 @@ create_fs_access(server_baton_t *b, apr_pool_t *pool)
* 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 +643,10 @@ static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
&& 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 +654,7 @@ static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +662,13 @@ static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +680,26 @@ internal_auth_request(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
{
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 +840,7 @@ static svn_error_t *must_have_access(svn_ra_svn_conn_t *conn,
*/
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 +849,9 @@ static svn_error_t *set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +867,12 @@ static svn_error_t *set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
}
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 +880,7 @@ static svn_error_t *delete_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
}
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 +889,7 @@ static svn_error_t *link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
/* 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 +911,7 @@ static svn_error_t *link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
}
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 +922,11 @@ static svn_error_t *finish_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +935,12 @@ static svn_error_t *abort_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +1105,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 +1127,11 @@ static svn_error_t *reparent(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +1144,18 @@ static svn_error_t *get_latest_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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", &timestr));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &timestr));
SVN_ERR(log_command(b, conn, pool, "get-dated-rev %s", timestr));
SVN_ERR(trivial_auth_request(conn, pool, b));
@@ -1171,8 +1193,11 @@ static svn_error_t *do_change_rev_prop(svn_ra_svn_conn_t *conn,
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 +1207,7 @@ static svn_error_t *change_rev_prop2(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +1233,11 @@ static svn_error_t *change_rev_prop2(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +1246,18 @@ static svn_error_t *change_rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
/* 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 +1267,7 @@ static svn_error_t *rev_proplist(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +1281,11 @@ static svn_error_t *rev_proplist(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +1296,7 @@ static svn_error_t *rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +1325,15 @@ static svn_error_t *commit_done(const svn_commit_info_t *commit_info,
/* 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 +1347,23 @@ static svn_error_t *add_lock_tokens(const apr_array_header_t *lock_tokens,
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 +1372,7 @@ static svn_error_t *add_lock_tokens(const apr_array_header_t *lock_tokens,
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 +1395,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 +1408,18 @@ static svn_error_t *unlock_paths(const apr_array_header_t *lock_tokens,
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 +1436,20 @@ static svn_error_t *unlock_paths(const apr_array_header_t *lock_tokens,
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 +1465,7 @@ static svn_error_t *commit(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
{
/* 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 +1473,7 @@ static svn_error_t *commit(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +1551,11 @@ static svn_error_t *commit(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 +1578,7 @@ static svn_error_t *get_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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,35 +1678,26 @@ static svn_error_t *get_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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)
+/* Translate all the words in DIRENT_FIELDS_LIST into the flags in
+ * DIRENT_FIELDS_P. If DIRENT_FIELDS_LIST is NULL, set all flags. */
+static svn_error_t *
+parse_dirent_fields(apr_uint32_t *dirent_fields_p,
+ svn_ra_svn__list_t *dirent_fields_list)
{
- server_baton_t *b = baton;
- const char *path, *full_path;
- svn_revnum_t rev;
- apr_hash_t *entries, *props = NULL;
- apr_array_header_t *inherited_props;
- apr_hash_index_t *hi;
- svn_fs_root_t *root;
- apr_pool_t *subpool;
- 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;
- 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,
- &want_props, &want_contents,
- &dirent_fields_list,
- &wants_inherited_props));
-
- if (wants_inherited_props == SVN_RA_SVN_UNSPECIFIED_NUMBER)
- wants_inherited_props = FALSE;
+ 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);
+
+ apr_uint32_t dirent_fields;
if (! dirent_fields_list)
{
@@ -1673,31 +1705,70 @@ static svn_error_t *get_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
}
else
{
+ int i;
dirent_fields = 0;
for (i = 0; i < dirent_fields_list->nelts; ++i)
{
- elt = &APR_ARRAY_IDX(dirent_fields_list, i, svn_ra_svn_item_t);
+ 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");
+ "Dirent field not a word");
- 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;
}
}
+ *dirent_fields_p = dirent_fields;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+get_dir(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;
+ svn_revnum_t rev;
+ apr_hash_t *entries, *props = NULL;
+ apr_array_header_t *inherited_props;
+ apr_hash_index_t *hi;
+ svn_fs_root_t *root;
+ apr_pool_t *subpool;
+ svn_boolean_t want_props, want_contents;
+ apr_uint64_t wants_inherited_props;
+ apr_uint32_t dirent_fields;
+ svn_ra_svn__list_t *dirent_fields_list = NULL;
+ int i;
+ authz_baton_t ab;
+
+ ab.server = b;
+ ab.conn = conn;
+
+ 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));
+
+ if (wants_inherited_props == SVN_RA_SVN_UNSPECIFIED_NUMBER)
+ wants_inherited_props = FALSE;
+
+ SVN_ERR(parse_dirent_fields(&dirent_fields, dirent_fields_list));
full_path = svn_fspath__join(b->repository->fs_path->data,
svn_relpath_canonicalize(path, pool), pool);
@@ -1773,7 +1844,7 @@ static svn_error_t *get_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
entry_kind = fsent->kind;
if (dirent_fields & SVN_DIRENT_SIZE)
- if (entry_kind != svn_node_dir)
+ if (fsent->kind != svn_node_dir)
SVN_CMD_ERR(svn_fs_file_length(&entry_size, root, file_path,
subpool));
@@ -1838,8 +1909,11 @@ static svn_error_t *get_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -1853,7 +1927,7 @@ static svn_error_t *update(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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);
@@ -1893,8 +1967,11 @@ static svn_error_t *update(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -1908,7 +1985,7 @@ static svn_error_t *switch_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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);
@@ -1943,8 +2020,11 @@ static svn_error_t *switch_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
(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;
@@ -1955,7 +2035,7 @@ static svn_error_t *status(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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);
@@ -1979,8 +2059,11 @@ static svn_error_t *status(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -1995,14 +2078,14 @@ static svn_error_t *diff(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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));
@@ -2039,31 +2122,92 @@ static svn_error_t *diff(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
return SVN_NO_ERROR;
}
+/* Baton type to be used with mergeinfo_receiver. */
+typedef struct mergeinfo_receiver_baton_t
+{
+ /* Send the response over this connection. */
+ svn_ra_svn_conn_t *conn;
+
+ /* Start path of the query; report paths relative to this one. */
+ const char *fs_path;
+
+ /* Did we already send the opening sequence? */
+ svn_boolean_t starting_tuple_sent;
+} mergeinfo_receiver_baton_t;
+
+/* Utility method sending the start of the "get m/i" response once
+ over BATON->CONN. */
+static svn_error_t *
+send_mergeinfo_starting_tuple(mergeinfo_receiver_baton_t *baton,
+ apr_pool_t *scratch_pool)
+{
+ if (baton->starting_tuple_sent)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_ra_svn__write_tuple(baton->conn, scratch_pool,
+ "w((!", "success"));
+ baton->starting_tuple_sent = TRUE;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_repos_mergeinfo_receiver_t, sending the MERGEINFO
+ * out over the connection in the mergeinfo_receiver_baton_t * BATON. */
+static svn_error_t *
+mergeinfo_receiver(const char *path,
+ svn_mergeinfo_t mergeinfo,
+ void *baton,
+ apr_pool_t *scratch_pool)
+{
+ mergeinfo_receiver_baton_t *b = baton;
+ svn_string_t *mergeinfo_string;
+
+ /* Delay starting the response until we checked that the initial
+ request went through. We are at that point now b/c we've got
+ the first results in. */
+ SVN_ERR(send_mergeinfo_starting_tuple(b, scratch_pool));
+
+ /* Adjust the path info and send the m/i. */
+ path = svn_fspath__skip_ancestor(b->fs_path, path);
+ SVN_ERR(svn_mergeinfo_to_string(&mergeinfo_string, mergeinfo,
+ scratch_pool));
+ SVN_ERR(svn_ra_svn__write_tuple(b->conn, scratch_pool, "cs", path,
+ mergeinfo_string));
+
+ return SVN_NO_ERROR;
+}
+
/* Regardless of whether a client's capabilities indicate an
understanding of this command (by way of SVN_RA_SVN_CAP_MERGEINFO),
we provide a response.
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_mergeinfo_catalog_t mergeinfo;
+ svn_ra_svn__list_t *paths;
+ apr_array_header_t *canonical_paths;
int i;
- apr_hash_index_t *hi;
const char *inherit_word;
svn_mergeinfo_inheritance_t inherit;
svn_boolean_t include_descendants;
- apr_pool_t *iterpool;
authz_baton_t ab;
+ mergeinfo_receiver_baton_t mergeinfo_baton;
ab.server = b;
ab.conn = conn;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "l(?r)wb", &paths, &rev,
+ mergeinfo_baton.conn = conn;
+ mergeinfo_baton.fs_path = b->repository->fs_path->data;
+ mergeinfo_baton.starting_tuple_sent = FALSE;
+
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "l(?r)wb", &paths, &rev,
&inherit_word, &include_descendants));
inherit = svn_inheritance_from_word(inherit_word);
@@ -2071,13 +2215,13 @@ static svn_error_t *get_mergeinfo(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
}
@@ -2088,42 +2232,76 @@ static svn_error_t *get_mergeinfo(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
pool)));
SVN_ERR(trivial_auth_request(conn, pool, b));
- SVN_CMD_ERR(svn_repos_fs_get_mergeinfo(&mergeinfo, b->repository->repos,
- canonical_paths, rev,
- inherit,
- include_descendants,
- authz_check_access_cb_func(b), &ab,
- pool));
- SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(&mergeinfo, mergeinfo,
- b->repository->fs_path->data, pool));
- SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "success"));
- iterpool = svn_pool_create(pool);
- for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
- {
- const char *key = apr_hash_this_key(hi);
- svn_mergeinfo_t value = apr_hash_this_val(hi);
- svn_string_t *mergeinfo_string;
- svn_pool_clear(iterpool);
+ SVN_CMD_ERR(svn_repos_fs_get_mergeinfo2(b->repository->repos,
+ canonical_paths, rev,
+ inherit,
+ include_descendants,
+ authz_check_access_cb_func(b), &ab,
+ mergeinfo_receiver,
+ &mergeinfo_baton,
+ pool));
+
+ /* We might not have sent anything
+ => ensure to begin the response in any case. */
+ SVN_ERR(send_mergeinfo_starting_tuple(&mergeinfo_baton, pool));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
+
+ return SVN_NO_ERROR;
+}
- SVN_ERR(svn_mergeinfo_to_string(&mergeinfo_string, value, iterpool));
- SVN_ERR(svn_ra_svn__write_tuple(conn, iterpool, "cs", key,
- mergeinfo_string));
+/* Send a changed paths list entry to the client.
+ This implements svn_repos_path_change_receiver_t. */
+static svn_error_t *
+path_change_receiver(void *baton,
+ svn_repos_path_change_t *change,
+ apr_pool_t *scratch_pool)
+{
+ const char symbol[] = "MADR";
+
+ log_baton_t *b = baton;
+ svn_ra_svn_conn_t *conn = b->conn;
+
+ /* Sanitize and convert change kind to ra-svn level action.
+
+ Pushing that conversion down into libsvn_ra_svn would add yet another
+ API dependency there. */
+ char action = ( change->change_kind < svn_fs_path_change_modify
+ || change->change_kind > svn_fs_path_change_replace)
+ ? 0
+ : symbol[change->change_kind];
+
+ /* Open lists once: LOG_ENTRY and LOG_ENTRY->CHANGED_PATHS. */
+ if (!b->started)
+ {
+ SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool));
+ SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool));
+ b->started = TRUE;
}
- svn_pool_destroy(iterpool);
- SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
+
+ /* Serialize CHANGE. */
+ SVN_ERR(svn_ra_svn__write_data_log_changed_path(
+ conn, scratch_pool,
+ &change->path,
+ action,
+ change->copyfrom_path,
+ change->copyfrom_rev,
+ change->node_kind,
+ change->text_mod,
+ change->prop_mod));
return SVN_NO_ERROR;
}
-/* Send a log entry to the client. */
-static svn_error_t *log_receiver(void *baton,
- svn_log_entry_t *log_entry,
- apr_pool_t *pool)
+/* Send a the meta data and the revpros for LOG_ENTRY to the client.
+ This implements svn_log_entry_receiver_t. */
+static svn_error_t *
+revision_receiver(void *baton,
+ svn_repos_log_entry_t *log_entry,
+ apr_pool_t *scratch_pool)
{
log_baton_t *b = baton;
svn_ra_svn_conn_t *conn = b->conn;
- apr_hash_index_t *h;
svn_boolean_t invalid_revnum = FALSE;
const svn_string_t *author, *date, *message;
unsigned revprop_count;
@@ -2144,55 +2322,52 @@ static svn_error_t *log_receiver(void *baton,
svn_compat_log_revprops_out_string(&author, &date, &message,
log_entry->revprops);
- svn_compat_log_revprops_clear(log_entry->revprops);
- if (log_entry->revprops)
- revprop_count = apr_hash_count(log_entry->revprops);
- else
- revprop_count = 0;
- /* send LOG_ENTRY */
- SVN_ERR(svn_ra_svn__start_list(conn, pool));
+ /* Revprops list filtering is somewhat expensive.
+ Avoid doing that for the 90% case where only the standard revprops
+ have been requested and delivered. */
+ if (author && date && message && apr_hash_count(log_entry->revprops) == 3)
+ {
+ revprop_count = 0;
+ }
+ else
+ {
+ svn_compat_log_revprops_clear(log_entry->revprops);
+ if (log_entry->revprops)
+ revprop_count = apr_hash_count(log_entry->revprops);
+ else
+ revprop_count = 0;
+ }
- /* send LOG_ENTRY->CHANGED_PATHS2 */
- SVN_ERR(svn_ra_svn__start_list(conn, pool));
- if (log_entry->changed_paths2)
+ /* Open lists once: LOG_ENTRY and LOG_ENTRY->CHANGED_PATHS. */
+ if (!b->started)
{
- for (h = apr_hash_first(pool, log_entry->changed_paths2); h;
- h = apr_hash_next(h))
- {
- const char *path = apr_hash_this_key(h);
- svn_log_changed_path2_t *change = apr_hash_this_val(h);
-
- SVN_ERR(svn_ra_svn__write_data_log_changed_path(
- conn, pool,
- path,
- change->action,
- change->copyfrom_path,
- change->copyfrom_rev,
- change->node_kind,
- /* text_modified and props_modified are never unknown */
- change->text_modified == svn_tristate_true,
- change->props_modified == svn_tristate_true));
- }
+ SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool));
+ SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool));
}
- SVN_ERR(svn_ra_svn__end_list(conn, pool));
+
+ /* Close LOG_ENTRY->CHANGED_PATHS. */
+ SVN_ERR(svn_ra_svn__end_list(conn, scratch_pool));
+ b->started = FALSE;
/* send LOG_ENTRY main members */
- SVN_ERR(svn_ra_svn__write_data_log_entry(conn, pool,
+ SVN_ERR(svn_ra_svn__write_data_log_entry(conn, scratch_pool,
log_entry->revision,
author, date, message,
log_entry->has_children,
invalid_revnum, revprop_count));
/* send LOG_ENTRY->REVPROPS */
- SVN_ERR(svn_ra_svn__start_list(conn, pool));
+ SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool));
if (revprop_count)
- SVN_ERR(svn_ra_svn__write_proplist(conn, pool, log_entry->revprops));
- SVN_ERR(svn_ra_svn__end_list(conn, pool));
+ SVN_ERR(svn_ra_svn__write_proplist(conn, scratch_pool,
+ log_entry->revprops));
+ SVN_ERR(svn_ra_svn__end_list(conn, scratch_pool));
/* send LOG_ENTRY members that were added in later SVN releases */
- SVN_ERR(svn_ra_svn__write_boolean(conn, pool, log_entry->subtractive_merge));
- SVN_ERR(svn_ra_svn__end_list(conn, pool));
+ SVN_ERR(svn_ra_svn__write_boolean(conn, scratch_pool,
+ log_entry->subtractive_merge));
+ SVN_ERR(svn_ra_svn__end_list(conn, scratch_pool));
if (log_entry->has_children)
b->stack_depth++;
@@ -2200,17 +2375,21 @@ static svn_error_t *log_receiver(void *baton,
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;
@@ -2219,7 +2398,7 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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,
@@ -2243,11 +2422,11 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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
@@ -2265,11 +2444,11 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -2286,11 +2465,14 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
lb.fs_path = b->repository->fs_path->data;
lb.conn = conn;
lb.stack_depth = 0;
- err = svn_repos_get_logs4(b->repository->repos, full_paths, start_rev,
- end_rev, (int) limit, send_changed_paths,
+ lb.started = FALSE;
+ err = svn_repos_get_logs5(b->repository->repos, full_paths, start_rev,
+ end_rev, (int) limit,
strict_node, include_merged_revisions,
revprops, authz_check_access_cb_func(b), &ab,
- log_receiver, &lb, pool);
+ send_changed_paths ? path_change_receiver : NULL,
+ send_changed_paths ? &lb : NULL,
+ revision_receiver, &lb, pool);
write_err = svn_ra_svn__write_word(conn, pool, "done");
if (write_err)
@@ -2303,8 +2485,11 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -2312,7 +2497,7 @@ static svn_error_t *check_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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);
@@ -2333,8 +2518,11 @@ static svn_error_t *check_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -2342,7 +2530,7 @@ static svn_error_t *stat_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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);
@@ -2380,14 +2568,18 @@ static svn_error_t *stat_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -2399,7 +2591,7 @@ static svn_error_t *get_locations(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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);
@@ -2411,7 +2603,7 @@ static svn_error_t *get_locations(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 "
@@ -2479,10 +2671,11 @@ static svn_error_t *gls_receiver(svn_location_segment_t *segment,
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;
@@ -2495,7 +2688,7 @@ static svn_error_t *get_location_segments(svn_ra_svn_conn_t *conn,
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);
@@ -2538,7 +2731,7 @@ static svn_error_t *get_location_segments(svn_ra_svn_conn_t *conn,
if (end_rev > start_rev)
{
err = svn_ra_svn__write_word(conn, pool, "done");
- err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, err,
+ 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);
@@ -2547,7 +2740,7 @@ static svn_error_t *get_location_segments(svn_ra_svn_conn_t *conn,
if (start_rev > peg_revision)
{
err = svn_ra_svn__write_word(conn, pool, "done");
- err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, err,
+ 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);
@@ -2628,15 +2821,9 @@ static svn_error_t *file_rev_handler(void *baton, const char *path,
svn_stream_set_write(stream, svndiff_handler);
svn_stream_set_close(stream, svndiff_close_handler);
- /* If the connection does not support SVNDIFF1 or if we don't want to use
- * compression, use the non-compressing "version 0" implementation */
- if ( svn_ra_svn_compression_level(frb->conn) > 0
- && svn_ra_svn_has_capability(frb->conn, SVN_RA_SVN_CAP_SVNDIFF1))
- svn_txdelta_to_svndiff3(d_handler, d_baton, stream, 1,
- svn_ra_svn_compression_level(frb->conn), pool);
- else
- svn_txdelta_to_svndiff3(d_handler, d_baton, stream, 0,
- svn_ra_svn_compression_level(frb->conn), pool);
+ svn_txdelta_to_svndiff3(d_handler, d_baton, stream,
+ svn_ra_svn__svndiff_version(frb->conn),
+ svn_ra_svn_compression_level(frb->conn), pool);
}
else
SVN_ERR(svn_ra_svn__write_cstring(frb->conn, pool, ""));
@@ -2644,8 +2831,11 @@ static svn_error_t *file_rev_handler(void *baton, const char *path,
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;
@@ -2661,7 +2851,7 @@ static svn_error_t *get_file_revs(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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);
@@ -2697,8 +2887,11 @@ static svn_error_t *get_file_revs(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -2708,7 +2901,7 @@ static svn_error_t *lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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, &current_rev));
full_path = svn_fspath__join(b->repository->fs_path->data,
svn_relpath_canonicalize(path, pool), pool);
@@ -2771,11 +2964,14 @@ clear_lock_result_hash(apr_hash_t *results,
}
}
-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;
@@ -2786,7 +2982,7 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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);
@@ -2802,8 +2998,7 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
{
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);
@@ -2812,7 +3007,7 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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,
&current_rev));
full_path = svn_fspath__join(b->repository->fs_path->data,
@@ -2866,14 +3061,13 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
{
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,
- &current_rev);
+ write_err = svn_ra_svn__parse_tuple(&item->u.list, "c(?r)",
+ &path, &current_rev);
if (write_err)
break;
@@ -2927,14 +3121,17 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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,
@@ -2954,12 +3151,15 @@ static svn_error_t *unlock(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -2968,8 +3168,7 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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));
@@ -2979,8 +3178,7 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
/* 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);
@@ -2989,7 +3187,7 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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 = "";
@@ -3042,14 +3240,13 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -3096,15 +3293,18 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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);
@@ -3124,8 +3324,11 @@ static svn_error_t *get_lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -3140,7 +3343,7 @@ static svn_error_t *get_locks(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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) &&
@@ -3213,14 +3416,17 @@ static svn_error_t *replay_one_revision(svn_ra_svn_conn_t *conn,
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));
@@ -3233,8 +3439,11 @@ static svn_error_t *replay(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -3245,7 +3454,7 @@ static svn_error_t *replay_range(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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));
@@ -3281,7 +3490,7 @@ static svn_error_t *replay_range(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
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;
@@ -3290,7 +3499,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);
@@ -3305,7 +3514,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;
@@ -3316,12 +3525,13 @@ get_inherited_props(svn_ra_svn_conn_t *conn,
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),
@@ -3331,15 +3541,18 @@ get_inherited_props(svn_ra_svn_conn_t *conn,
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. */
@@ -3365,7 +3578,115 @@ get_inherited_props(svn_ra_svn_conn_t *conn,
return SVN_NO_ERROR;
}
-static const svn_ra_svn_cmd_entry_t main_commands[] = {
+/* Baton type to be used with list_receiver. */
+typedef struct list_receiver_baton_t
+{
+ /* Send the data through this connection. */
+ svn_ra_svn_conn_t *conn;
+
+ /* Send the field selected by these flags. */
+ apr_uint32_t dirent_fields;
+} list_receiver_baton_t;
+
+/* Implements svn_repos_dirent_receiver_t, sending DIRENT and PATH to the
+ * client. BATON must be a list_receiver_baton_t. */
+static svn_error_t *
+list_receiver(const char *path,
+ svn_dirent_t *dirent,
+ void *baton,
+ apr_pool_t *pool)
+{
+ list_receiver_baton_t *b = baton;
+ return svn_error_trace(svn_ra_svn__write_dirent(b->conn, pool, path, dirent,
+ b->dirent_fields));
+}
+
+static svn_error_t *
+list(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;
+ svn_revnum_t rev;
+ svn_depth_t depth;
+ apr_array_header_t *patterns = NULL;
+ svn_fs_root_t *root;
+ const char *depth_word;
+ svn_boolean_t path_info_only;
+ svn_ra_svn__list_t *dirent_fields_list = NULL;
+ svn_ra_svn__list_t *patterns_list = NULL;
+ int i;
+ list_receiver_baton_t rb;
+ svn_error_t *err, *write_err;
+
+ authz_baton_t ab;
+ ab.server = b;
+ ab.conn = conn;
+
+ /* Read the command parameters. */
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)w?l?l", &path, &rev,
+ &depth_word, &dirent_fields_list,
+ &patterns_list));
+
+ rb.conn = conn;
+ SVN_ERR(parse_dirent_fields(&rb.dirent_fields, dirent_fields_list));
+
+ depth = svn_depth_from_word(depth_word);
+ full_path = svn_fspath__join(b->repository->fs_path->data,
+ svn_relpath_canonicalize(path, pool), pool);
+
+ /* Read the patterns list. */
+ if (patterns_list)
+ {
+ patterns = apr_array_make(pool, 0, sizeof(const char *));
+ for (i = 0; i < patterns_list->nelts; ++i)
+ {
+ svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(patterns_list, i);
+
+ if (elt->kind != SVN_RA_SVN_STRING)
+ return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ "Pattern field not a string");
+
+ APR_ARRAY_PUSH(patterns, const char *) = elt->u.string.data;
+ }
+ }
+
+ /* Check authorizations */
+ SVN_ERR(must_have_access(conn, pool, 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__list(full_path, rev, patterns, depth,
+ rb.dirent_fields, pool)));
+
+ /* Fetch the root of the appropriate revision. */
+ SVN_CMD_ERR(svn_fs_revision_root(&root, b->repository->fs, rev, pool));
+
+ /* Fetch the directory entries if requested and send them immediately. */
+ path_info_only = (rb.dirent_fields & ~SVN_DIRENT_KIND) == 0;
+ err = svn_repos_list(root, full_path, patterns, depth, path_info_only,
+ authz_check_access_cb_func(b), &ab, list_receiver,
+ &rb, NULL, NULL, pool);
+
+
+ /* Finish response. */
+ write_err = svn_ra_svn__write_word(conn, pool, "done");
+ if (write_err)
+ {
+ svn_error_clear(err);
+ return write_err;
+ }
+ SVN_CMD_ERR(err);
+
+ return svn_error_trace(svn_ra_svn__write_cmd_response(conn, pool, ""));
+}
+
+static const svn_ra_svn__cmd_entry_t main_commands[] = {
{ "reparent", reparent },
{ "get-latest-rev", get_latest_rev },
{ "get-dated-rev", get_dated_rev },
@@ -3397,6 +3718,7 @@ static const svn_ra_svn_cmd_entry_t main_commands[] = {
{ "replay-range", replay_range },
{ "get-deleted-rev", get_deleted_rev },
{ "get-iprops", get_inherited_props },
+ { "list", list },
{ NULL }
};
@@ -3457,8 +3779,7 @@ repos_path_valid(const char *path)
* and fs_path fields of REPOSITORY. VHOST and READ_ONLY flags are the
* same as in the server baton.
*
- * CONFIG_POOL and AUTHZ_POOL shall be used to load any object of the
- * respective type.
+ * CONFIG_POOL shall be used to load config objects.
*
* Use SCRATCH_POOL for temporary allocations.
*
@@ -3471,13 +3792,13 @@ find_repos(const char *url,
svn_config_t *cfg,
repository_t *repository,
svn_repos__config_pool_t *config_pool,
- svn_repos__authz_pool_t *authz_pool,
apr_hash_t *fs_config,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
const char *path, *full_path, *fs_path, *hooks_env;
svn_stringbuf_t *url_buf;
+ svn_boolean_t sasl_requested;
/* Skip past the scheme and authority part. */
path = skip_scheme_part(url);
@@ -3540,25 +3861,27 @@ find_repos(const char *url,
{
repository->base = svn_repos_conf_dir(repository->repos, result_pool);
- SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+ SVN_ERR(svn_repos__config_pool_get(&cfg, config_pool,
svn_repos_svnserve_conf
(repository->repos, result_pool),
- FALSE, FALSE, repository->repos,
+ FALSE, repository->repos,
result_pool));
}
SVN_ERR(load_pwdb_config(repository, cfg, config_pool, result_pool));
SVN_ERR(load_authz_config(repository, repository->repos_root, cfg,
- authz_pool, result_pool));
+ result_pool));
-#ifdef SVN_HAVE_SASL
+ /* Should we use Cyrus SASL? */
+ SVN_ERR(svn_config_get_bool(cfg, &sasl_requested,
+ SVN_CONFIG_SECTION_SASL,
+ SVN_CONFIG_OPTION_USE_SASL, FALSE));
+ if (sasl_requested)
{
+#ifdef SVN_HAVE_SASL
const char *val;
- /* Should we use Cyrus SASL? */
- SVN_ERR(svn_config_get_bool(cfg, &repository->use_sasl,
- SVN_CONFIG_SECTION_SASL,
- SVN_CONFIG_OPTION_USE_SASL, FALSE));
+ repository->use_sasl = sasl_requested;
svn_config_get(cfg, &val, SVN_CONFIG_SECTION_SASL,
SVN_CONFIG_OPTION_MIN_SSF, "0");
@@ -3567,8 +3890,18 @@ find_repos(const char *url,
svn_config_get(cfg, &val, SVN_CONFIG_SECTION_SASL,
SVN_CONFIG_OPTION_MAX_SSF, "256");
SVN_ERR(svn_cstring_atoui(&repository->max_ssf, val));
+#else /* !SVN_HAVE_SASL */
+ return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
+ _("SASL requested but not compiled in; "
+ "set '%s' to 'false' or recompile "
+ "svnserve with SASL support"),
+ SVN_CONFIG_OPTION_USE_SASL);
+#endif /* SVN_HAVE_SASL */
+ }
+ else
+ {
+ repository->use_sasl = FALSE;
}
-#endif
/* Use the repository UUID as the default realm. */
SVN_ERR(svn_fs_get_uuid(repository->fs, &repository->realm, scratch_pool));
@@ -3771,7 +4104,7 @@ construct_server_baton(server_baton_t **baton,
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;
@@ -3796,10 +4129,11 @@ construct_server_baton(server_baton_t **baton,
* send an empty mechlist. */
if (params->compression_level > 0)
SVN_ERR(svn_ra_svn__write_cmd_response(conn, scratch_pool,
- "nn()(wwwwwwwwwww)",
+ "nn()(wwwwwwwwwwwww)",
(apr_uint64_t) 2, (apr_uint64_t) 2,
SVN_RA_SVN_CAP_EDIT_PIPELINE,
SVN_RA_SVN_CAP_SVNDIFF1,
+ SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED,
SVN_RA_SVN_CAP_ABSENT_ENTRIES,
SVN_RA_SVN_CAP_COMMIT_REVPROPS,
SVN_RA_SVN_CAP_DEPTH,
@@ -3808,11 +4142,12 @@ construct_server_baton(server_baton_t **baton,
SVN_RA_SVN_CAP_PARTIAL_REPLAY,
SVN_RA_SVN_CAP_INHERITED_PROPS,
SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS,
- SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE
+ SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE,
+ SVN_RA_SVN_CAP_LIST
));
else
SVN_ERR(svn_ra_svn__write_cmd_response(conn, scratch_pool,
- "nn()(wwwwwwwwww)",
+ "nn()(wwwwwwwwwww)",
(apr_uint64_t) 2, (apr_uint64_t) 2,
SVN_RA_SVN_CAP_EDIT_PIPELINE,
SVN_RA_SVN_CAP_ABSENT_ENTRIES,
@@ -3823,7 +4158,8 @@ construct_server_baton(server_baton_t **baton,
SVN_RA_SVN_CAP_PARTIAL_REPLAY,
SVN_RA_SVN_CAP_INHERITED_PROPS,
SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS,
- SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE
+ SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE,
+ SVN_RA_SVN_CAP_LIST
));
/* Read client response, which we assume to be in version 2 format:
@@ -3837,7 +4173,7 @@ construct_server_baton(server_baton_t **baton,
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. */
@@ -3848,22 +4184,25 @@ construct_server_baton(server_baton_t **baton,
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;
@@ -3871,14 +4210,14 @@ construct_server_baton(server_baton_t **baton,
/* 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);
}
}
err = handle_config_error(find_repos(client_url, params->root, b->vhost,
b->read_only, params->cfg,
b->repository, params->config_pool,
- params->authz_pool, params->fs_config,
+ params->fs_config,
conn_pool, scratch_pool),
b);
if (!err)
@@ -3980,7 +4319,7 @@ serve_interruptable(svn_boolean_t *terminate_p,
{
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. */
@@ -4009,10 +4348,12 @@ serve_interruptable(svn_boolean_t *terminate_p,
/* 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. */