diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-04-29 19:16:59 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-04-29 19:16:59 +0000 |
commit | c94cceea9c2262c5b2ad5f215bb9a8ae48b02764 (patch) | |
tree | dbb8174cbf6f1cc45b8de8031b18adb4030509a8 /subversion/libsvn_ra_serf | |
parent | dc5d469d6574e9fb03bdd793658bb371315b306a (diff) |
Notes
Diffstat (limited to 'subversion/libsvn_ra_serf')
-rw-r--r-- | subversion/libsvn_ra_serf/commit.c | 68 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/inherited_props.c | 4 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/merge.c | 16 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/multistatus.c | 10 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/ra_serf.h | 18 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/replay.c | 1 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/serf.c | 58 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/util.c | 26 |
8 files changed, 141 insertions, 60 deletions
diff --git a/subversion/libsvn_ra_serf/commit.c b/subversion/libsvn_ra_serf/commit.c index ec3bce9455897..b1e81c7870e3d 100644 --- a/subversion/libsvn_ra_serf/commit.c +++ b/subversion/libsvn_ra_serf/commit.c @@ -101,6 +101,8 @@ typedef struct delete_context_t { svn_revnum_t revision; commit_context_t *commit_ctx; + + svn_boolean_t non_recursive_if; /* Only create a non-recursive If header */ } delete_context_t; /* Represents a directory. */ @@ -841,6 +843,7 @@ proppatch_resource(svn_ra_serf__session_t *session, handler->body_delegate = create_proppatch_body; handler->body_delegate_baton = proppatch; + handler->body_type = "text/xml"; handler->response_handler = svn_ra_serf__handle_multistatus_only; handler->response_baton = handler; @@ -1101,8 +1104,15 @@ setup_delete_headers(serf_bucket_t *headers, serf_bucket_headers_set(headers, SVN_DAV_VERSION_NAME_HEADER, apr_ltoa(pool, del->revision)); - SVN_ERR(setup_if_header_recursive(&added, headers, del->commit_ctx, - del->relpath, pool)); + if (! del->non_recursive_if) + SVN_ERR(setup_if_header_recursive(&added, headers, del->commit_ctx, + del->relpath, pool)); + else + { + SVN_ERR(maybe_set_lock_token_header(headers, del->commit_ctx, + del->relpath, pool)); + added = TRUE; + } if (added && del->commit_ctx->keep_locks) serf_bucket_headers_setn(headers, SVN_DAV_OPTIONS_HEADER, @@ -1402,6 +1412,28 @@ open_root(void *edit_baton, return SVN_NO_ERROR; } +/* Implements svn_ra_serf__request_body_delegate_t */ +static svn_error_t * +create_delete_body(serf_bucket_t **body_bkt, + void *baton, + serf_bucket_alloc_t *alloc, + apr_pool_t *pool /* request pool */, + apr_pool_t *scratch_pool) +{ + delete_context_t *ctx = baton; + serf_bucket_t *body; + + body = serf_bucket_aggregate_create(alloc); + + svn_ra_serf__add_xml_header_buckets(body, alloc); + + svn_ra_serf__merge_lock_token_list(ctx->commit_ctx->lock_tokens, + ctx->relpath, body, alloc, pool); + + *body_bkt = body; + return SVN_NO_ERROR; +} + static svn_error_t * delete_entry(const char *path, svn_revnum_t revision, @@ -1445,9 +1477,37 @@ delete_entry(const char *path, handler->method = "DELETE"; handler->path = delete_target; + handler->no_fail_on_http_failure_status = TRUE; SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); + if (handler->sline.code == 400) + { + /* Try again with non-standard body to overcome Apache Httpd + header limit */ + delete_ctx->non_recursive_if = TRUE; + + handler = svn_ra_serf__create_handler(dir->commit_ctx->session, pool); + + handler->response_handler = svn_ra_serf__expect_empty_body; + handler->response_baton = handler; + + handler->header_delegate = setup_delete_headers; + handler->header_delegate_baton = delete_ctx; + + handler->method = "DELETE"; + handler->path = delete_target; + + handler->body_type = "text/xml"; + handler->body_delegate = create_delete_body; + handler->body_delegate_baton = delete_ctx; + + SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); + } + + if (handler->server_error) + return svn_ra_serf__server_error_create(handler, pool); + /* 204 No Content: item successfully deleted */ if (handler->sline.code != 204) return svn_error_trace(svn_ra_serf__unexpected_status(handler)); @@ -1539,7 +1599,9 @@ add_directory(const char *path, handler->header_delegate = setup_copy_dir_headers; handler->header_delegate_baton = dir; } - + /* We have the same problem as with DELETE here: if there are too many + locks, the request fails. But in this case there is no way to retry + with a non-standard request. #### How to fix? */ SVN_ERR(svn_ra_serf__context_run_one(handler, dir->pool)); if (handler->sline.code != 201) diff --git a/subversion/libsvn_ra_serf/inherited_props.c b/subversion/libsvn_ra_serf/inherited_props.c index 40acc5d6f14f6..6edafb1027cfb 100644 --- a/subversion/libsvn_ra_serf/inherited_props.c +++ b/subversion/libsvn_ra_serf/inherited_props.c @@ -143,9 +143,7 @@ iprops_closed(svn_ra_serf__xml_estate_t *xes, return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL); iprops_ctx->curr_iprop->path_or_url = - svn_path_url_add_component2(iprops_ctx->repos_root_url, - cdata->data, - iprops_ctx->pool); + apr_pstrdup(iprops_ctx->pool, cdata->data); } else if (leaving_state == IPROPS_PROPNAME) { diff --git a/subversion/libsvn_ra_serf/merge.c b/subversion/libsvn_ra_serf/merge.c index 2465b8fd2bc48..0a2fd5465b590 100644 --- a/subversion/libsvn_ra_serf/merge.c +++ b/subversion/libsvn_ra_serf/merge.c @@ -285,12 +285,12 @@ setup_merge_headers(serf_bucket_t *headers, return SVN_NO_ERROR; } -static void -merge_lock_token_list(apr_hash_t *lock_tokens, - const char *parent, - serf_bucket_t *body, - serf_bucket_alloc_t *alloc, - apr_pool_t *pool) +void +svn_ra_serf__merge_lock_token_list(apr_hash_t *lock_tokens, + const char *parent, + serf_bucket_t *body, + serf_bucket_alloc_t *alloc, + apr_pool_t *pool) { apr_hash_index_t *hi; @@ -378,7 +378,8 @@ create_merge_body(serf_bucket_t **bkt, "D:creator-displayname", SVN_VA_NULL); svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop"); - merge_lock_token_list(ctx->lock_tokens, NULL, body_bkt, alloc, pool); + svn_ra_serf__merge_lock_token_list(ctx->lock_tokens, NULL, body_bkt, + alloc, pool); svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:merge"); @@ -426,6 +427,7 @@ svn_ra_serf__run_merge(const svn_commit_info_t **commit_info, handler->path = merge_ctx->merge_url; handler->body_delegate = create_merge_body; handler->body_delegate_baton = merge_ctx; + handler->body_type = "text/xml"; handler->header_delegate = setup_merge_headers; handler->header_delegate_baton = merge_ctx; diff --git a/subversion/libsvn_ra_serf/multistatus.c b/subversion/libsvn_ra_serf/multistatus.c index 5b4c8fd0c0f51..9c269c39beddf 100644 --- a/subversion/libsvn_ra_serf/multistatus.c +++ b/subversion/libsvn_ra_serf/multistatus.c @@ -315,7 +315,7 @@ multistatus_closed(svn_ra_serf__xml_estate_t *xes, svn_ra_serf__xml_note(xes, MS_RESPONSE, "errcode", errcode); break; case MS_RESPONSE: - if ((status = svn_hash_gets(attrs, "status")) != NULL) + if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL) { error_item_t *item; @@ -369,7 +369,7 @@ multistatus_closed(svn_ra_serf__xml_estate_t *xes, break; case MS_PROPSTAT: - if ((status = svn_hash_gets(attrs, "status")) != NULL) + if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL) { apr_hash_t *response_attrs; error_item_t *item; @@ -428,7 +428,8 @@ multistatus_closed(svn_ra_serf__xml_estate_t *xes, item->http_status = server_error->handler->sline.code; /* Do we have a mod_dav specific message? */ - item->message = svn_hash_gets(attrs, "human-readable"); + item->message = svn_hash__get_cstring(attrs, "human-readable", + NULL); if (item->message) { @@ -442,9 +443,6 @@ multistatus_closed(svn_ra_serf__xml_estate_t *xes, item->message = apr_pstrdup(server_error->pool, item->message); } - else - item->message = apr_pstrdup(server_error->pool, - svn_hash_gets(attrs, "description")); APR_ARRAY_PUSH(server_error->items, error_item_t *) = item; diff --git a/subversion/libsvn_ra_serf/ra_serf.h b/subversion/libsvn_ra_serf/ra_serf.h index 510a6b5ebc817..fcef73777a03d 100644 --- a/subversion/libsvn_ra_serf/ra_serf.h +++ b/subversion/libsvn_ra_serf/ra_serf.h @@ -1022,6 +1022,13 @@ svn_ra_serf__svnname_from_wirename(const char *ns, /** MERGE-related functions **/ +void +svn_ra_serf__merge_lock_token_list(apr_hash_t *lock_tokens, + const char *parent, + serf_bucket_t *body, + serf_bucket_alloc_t *alloc, + apr_pool_t *pool); + /* Create an MERGE request aimed at the SESSION url, requesting the merge of the resource identified by MERGE_RESOURCE_URL. LOCK_TOKENS is a hash mapping paths to lock tokens owned by the @@ -1538,6 +1545,17 @@ svn_ra_serf__create_bucket_with_eagain(const char *data, apr_size_t len, serf_bucket_alloc_t *allocator); +/* Parse a given URL_STR, fill in all supplied fields of URI + * structure. + * + * This function is a compatibility wrapper around apr_uri_parse(). + * Different apr-util versions set apr_uri_t.path to either NULL or "" + * for root paths, and serf expects to see "/". This function always + * sets URI.path to "/" for these paths. */ +svn_error_t * +svn_ra_serf__uri_parse(apr_uri_t *uri, + const char *url_str, + apr_pool_t *result_pool); #if defined(SVN_DEBUG) diff --git a/subversion/libsvn_ra_serf/replay.c b/subversion/libsvn_ra_serf/replay.c index d9a2ed6992b2d..8d2da69fa4ebe 100644 --- a/subversion/libsvn_ra_serf/replay.c +++ b/subversion/libsvn_ra_serf/replay.c @@ -756,6 +756,7 @@ svn_ra_serf__replay_range(svn_ra_session_t *ra_session, handler->path = replay_target; handler->body_delegate = create_replay_body; handler->body_delegate_baton = rev_ctx; + handler->body_type = "text/xml"; handler->done_delegate = replay_done; handler->done_delegate_baton = rev_ctx; diff --git a/subversion/libsvn_ra_serf/serf.c b/subversion/libsvn_ra_serf/serf.c index ab28ca0407908..3c47d5eae9009 100644 --- a/subversion/libsvn_ra_serf/serf.c +++ b/subversion/libsvn_ra_serf/serf.c @@ -64,7 +64,7 @@ ra_serf_version(void) #define RA_SERF_DESCRIPTION_VER \ N_("Module for accessing a repository via WebDAV protocol using serf.\n" \ - " - using serf %d.%d.%d") + " - using serf %d.%d.%d (compiled with %d.%d.%d)") /* Implements svn_ra__vtable_t.get_description(). */ static const char * @@ -73,7 +73,12 @@ ra_serf_get_description(apr_pool_t *pool) int major, minor, patch; serf_lib_version(&major, &minor, &patch); - return apr_psprintf(pool, _(RA_SERF_DESCRIPTION_VER), major, minor, patch); + return apr_psprintf(pool, _(RA_SERF_DESCRIPTION_VER), + major, minor, patch, + SERF_MAJOR_VERSION, + SERF_MINOR_VERSION, + SERF_PATCH_VERSION + ); } /* Implements svn_ra__vtable_t.get_schemes(). */ @@ -509,19 +514,8 @@ svn_ra_serf__open(svn_ra_session_t *session, serf_sess->pool)); - status = apr_uri_parse(serf_sess->pool, session_URL, &url); - if (status) - { - return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, - _("Illegal URL '%s'"), - session_URL); - } - /* Depending the version of apr-util in use, for root paths url.path - will be NULL or "", where serf requires "/". */ - if (url.path == NULL || url.path[0] == '\0') - { - url.path = apr_pstrdup(serf_sess->pool, "/"); - } + SVN_ERR(svn_ra_serf__uri_parse(&url, session_URL, serf_sess->pool)); + if (!url.port) { url.port = apr_uri_port_of_scheme(url.scheme); @@ -741,18 +735,15 @@ ra_serf_dup_session(svn_ra_session_t *new_session, new_sess->repos_root_str = apr_pstrdup(result_pool, new_sess->repos_root_str); - status = apr_uri_parse(result_pool, new_sess->repos_root_str, - &new_sess->repos_root); - if (status) - return svn_ra_serf__wrap_err(status, NULL); + SVN_ERR(svn_ra_serf__uri_parse(&new_sess->repos_root, + new_sess->repos_root_str, + result_pool)); new_sess->session_url_str = apr_pstrdup(result_pool, new_session_url); - status = apr_uri_parse(result_pool, new_sess->session_url_str, - &new_sess->session_url); - - if (status) - return svn_ra_serf__wrap_err(status, NULL); + SVN_ERR(svn_ra_serf__uri_parse(&new_sess->session_url, + new_sess->session_url_str, + result_pool)); /* svn_boolean_t supports_inline_props */ /* supports_rev_rsrc_replay */ @@ -799,7 +790,6 @@ svn_ra_serf__reparent(svn_ra_session_t *ra_session, { svn_ra_serf__session_t *session = ra_session->priv; apr_uri_t new_url; - apr_status_t status; /* If it's the URL we already have, wave our hands and do nothing. */ if (strcmp(session->session_url_str, url) == 0) @@ -821,25 +811,11 @@ svn_ra_serf__reparent(svn_ra_session_t *ra_session, "URL '%s'"), url, session->repos_root_str); } - status = apr_uri_parse(pool, url, &new_url); - if (status) - { - return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, - _("Illegal repository URL '%s'"), url); - } + SVN_ERR(svn_ra_serf__uri_parse(&new_url, url, pool)); - /* Depending the version of apr-util in use, for root paths url.path - will be NULL or "", where serf requires "/". */ /* ### Maybe we should use a string buffer for these strings so we ### don't allocate memory in the session on every reparent? */ - if (new_url.path == NULL || new_url.path[0] == '\0') - { - session->session_url.path = apr_pstrdup(session->pool, "/"); - } - else - { - session->session_url.path = apr_pstrdup(session->pool, new_url.path); - } + session->session_url.path = apr_pstrdup(session->pool, new_url.path); session->session_url_str = apr_pstrdup(session->pool, url); return SVN_NO_ERROR; diff --git a/subversion/libsvn_ra_serf/util.c b/subversion/libsvn_ra_serf/util.c index 98f1f4a8cd638..5490ddea8a592 100644 --- a/subversion/libsvn_ra_serf/util.c +++ b/subversion/libsvn_ra_serf/util.c @@ -1949,3 +1949,29 @@ svn_ra_serf__create_handler(svn_ra_serf__session_t *session, return handler; } +svn_error_t * +svn_ra_serf__uri_parse(apr_uri_t *uri, + const char *url_str, + apr_pool_t *result_pool) +{ + apr_status_t status; + + status = apr_uri_parse(result_pool, url_str, uri); + if (status) + { + /* Do not use returned error status in error message because currently + apr_uri_parse() returns APR_EGENERAL for all parsing errors. */ + return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, + _("Illegal URL '%s'"), + url_str); + } + + /* Depending the version of apr-util in use, for root paths uri.path + will be NULL or "", where serf requires "/". */ + if (uri->path == NULL || uri->path[0] == '\0') + { + uri->path = apr_pstrdup(result_pool, "/"); + } + + return SVN_NO_ERROR; +} |