Modified: subversion/branches/master-passphrase/subversion/libsvn_ra_serf/merge.c URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_ra_serf/merge.c?rev=1354571&r1=1354570&r2=1354571&view=diff ============================================================================== --- subversion/branches/master-passphrase/subversion/libsvn_ra_serf/merge.c (original) +++ subversion/branches/master-passphrase/subversion/libsvn_ra_serf/merge.c Wed Jun 27 15:12:37 2012 @@ -47,7 +47,7 @@ * This enum represents the current state of our XML parsing for a MERGE. */ typedef enum merge_state_e { - NONE = 0, + INITIAL = 0, MERGE_RESPONSE, UPDATED_SET, RESPONSE, @@ -55,41 +55,26 @@ typedef enum merge_state_e { PROPSTAT, PROP, RESOURCE_TYPE, - AUTHOR, - NAME, - DATE, - IGNORE_PROP_NAME, - NEED_PROP_NAME, - PROP_VAL -} merge_state_e; - -typedef enum resource_type_e { - UNSET, BASELINE, COLLECTION, - CHECKED_IN -} resource_type_e; - -typedef struct merge_info_t { - /* Temporary allocations here please */ - apr_pool_t *pool; - - resource_type_e type; - - apr_hash_t *props; + SKIP_HREF, + CHECKED_IN, + VERSION_NAME, + DATE, + AUTHOR, + POST_COMMIT_ERR, - const char *prop_ns; - const char *prop_name; - svn_stringbuf_t *prop_value; + PROP_VAL +} merge_state_e; -} merge_info_t; /* Structure associated with a MERGE request. */ -struct svn_ra_serf__merge_context_t +typedef struct merge_context_t { apr_pool_t *pool; svn_ra_serf__session_t *session; + svn_ra_serf__handler_t *handler; apr_hash_t *lock_tokens; svn_boolean_t keep_locks; @@ -97,310 +82,194 @@ struct svn_ra_serf__merge_context_t const char *merge_resource_url; /* URL of resource to be merged. */ const char *merge_url; /* URL at which the MERGE request is aimed. */ - int status; + svn_commit_info_t *commit_info; - svn_boolean_t done; +} merge_context_t; - svn_commit_info_t *commit_info; -}; - -static merge_info_t * -push_state(svn_ra_serf__xml_parser_t *parser, - svn_ra_serf__merge_context_t *ctx, - merge_state_e state) -{ - merge_info_t *info; +#define D_ "DAV:" +#define S_ SVN_XML_NAMESPACE +static const svn_ra_serf__xml_transition_t merge_ttable[] = { + { INITIAL, D_, "merge-response", MERGE_RESPONSE, + FALSE, { NULL }, FALSE }, - svn_ra_serf__xml_push_state(parser, state); + { MERGE_RESPONSE, D_, "updated-set", UPDATED_SET, + FALSE, { NULL }, FALSE }, - if (state == RESPONSE) - { - info = apr_palloc(parser->state->pool, sizeof(*info)); - info->pool = parser->state->pool; - info->props = apr_hash_make(info->pool); - info->prop_value = svn_stringbuf_create_empty(info->pool); + { UPDATED_SET, D_, "response", RESPONSE, + FALSE, { NULL }, TRUE }, - parser->state->private = info; - } + { RESPONSE, D_, "href", HREF, + TRUE, { NULL }, TRUE }, - return parser->state->private; -} + { RESPONSE, D_, "propstat", PROPSTAT, + FALSE, { NULL }, FALSE }, -static svn_error_t * -start_merge(svn_ra_serf__xml_parser_t *parser, - svn_ra_serf__dav_props_t name, - const char **attrs, - apr_pool_t *scratch_pool) -{ - svn_ra_serf__merge_context_t *ctx = parser->user_data; - merge_state_e state; - merge_info_t *info; +#if 0 + /* Not needed. */ + { PROPSTAT, D_, "status", STATUS, + FALSE, { NULL }, FALSE }, +#endif - state = parser->state->current_state; + { PROPSTAT, D_, "prop", PROP, + FALSE, { NULL }, FALSE }, - if (state == NONE && - strcmp(name.name, "merge-response") == 0) - { - push_state(parser, ctx, MERGE_RESPONSE); - } - else if (state == NONE) - { - /* do nothing as we haven't seen our valid start tag yet. */ - } - else if (state == MERGE_RESPONSE && - strcmp(name.name, "updated-set") == 0) - { - push_state(parser, ctx, UPDATED_SET); - } - else if (state == UPDATED_SET && - strcmp(name.name, "response") == 0) - { - push_state(parser, ctx, RESPONSE); - } - else if (state == RESPONSE && - strcmp(name.name, "href") == 0) - { - info = push_state(parser, ctx, PROP_VAL); + { PROP, D_, "resourcetype", RESOURCE_TYPE, + FALSE, { NULL }, FALSE }, - info->prop_ns = name.namespace; - info->prop_name = "href"; - svn_stringbuf_setempty(info->prop_value); - } - else if (state == RESPONSE && - strcmp(name.name, "propstat") == 0) - { - push_state(parser, ctx, PROPSTAT); - } - else if (state == PROPSTAT && - strcmp(name.name, "prop") == 0) - { - push_state(parser, ctx, PROP); - } - else if (state == PROPSTAT && - strcmp(name.name, "status") == 0) - { - /* Do nothing for now. */ - } - else if (state == PROP && - strcmp(name.name, "resourcetype") == 0) - { - info = push_state(parser, ctx, RESOURCE_TYPE); - info->type = UNSET; - } - else if (state == RESOURCE_TYPE && - strcmp(name.name, "baseline") == 0) - { - info = parser->state->private; + { RESOURCE_TYPE, D_, "baseline", BASELINE, + FALSE, { NULL }, TRUE }, - info->type = BASELINE; - } - else if (state == RESOURCE_TYPE && - strcmp(name.name, "collection") == 0) - { - info = parser->state->private; + { RESOURCE_TYPE, D_, "collection", COLLECTION, + FALSE, { NULL }, TRUE }, - info->type = COLLECTION; - } - else if (state == PROP && - strcmp(name.name, "checked-in") == 0) - { - info = push_state(parser, ctx, IGNORE_PROP_NAME); - info->prop_ns = name.namespace; - info->prop_name = "checked-in"; - svn_stringbuf_setempty(info->prop_value); - } - else if (state == PROP) - { - push_state(parser, ctx, PROP_VAL); - } - else if (state == IGNORE_PROP_NAME) - { - push_state(parser, ctx, PROP_VAL); - } - else if (state == NEED_PROP_NAME) - { - info = push_state(parser, ctx, PROP_VAL); - info->prop_ns = name.namespace; - info->prop_name = apr_pstrdup(info->pool, name.name); - svn_stringbuf_setempty(info->prop_value); - } - else - { - SVN_ERR_MALFUNCTION(); - } + { PROP, D_, "checked-in", SKIP_HREF, + FALSE, { NULL }, FALSE }, - return SVN_NO_ERROR; -} + { SKIP_HREF, D_, "href", CHECKED_IN, + TRUE, { NULL }, TRUE }, + + { PROP, D_, SVN_DAV__VERSION_NAME, VERSION_NAME, + TRUE, { NULL }, TRUE }, + + { PROP, D_, SVN_DAV__CREATIONDATE, DATE, + TRUE, { NULL }, TRUE }, + + { PROP, D_, "creator-displayname", AUTHOR, + TRUE, { NULL }, TRUE }, + { PROP, S_, "post-commit-err", POST_COMMIT_ERR, + TRUE, { NULL }, TRUE }, + + { 0 } +}; + + +/* Conforms to svn_ra_serf__xml_closed_t */ static svn_error_t * -end_merge(svn_ra_serf__xml_parser_t *parser, - svn_ra_serf__dav_props_t name, - apr_pool_t *scratch_pool) +merge_closed(svn_ra_serf__xml_estate_t *xes, + void *baton, + int leaving_state, + const svn_string_t *cdata, + apr_hash_t *attrs, + apr_pool_t *scratch_pool) { - svn_ra_serf__merge_context_t *ctx = parser->user_data; - merge_state_e state; - merge_info_t *info; + merge_context_t *merge_ctx = baton; - state = parser->state->current_state; - info = parser->state->private; - - if (state == NONE) + if (leaving_state == RESPONSE) { - /* nothing to close yet. */ - return SVN_NO_ERROR; - } + const char *rtype; - if (state == RESPONSE && - strcmp(name.name, "response") == 0) - { - if (info->type == BASELINE) + rtype = apr_hash_get(attrs, "resourcetype", APR_HASH_KEY_STRING); + + /* rtype can only be "baseline" or "collection" (or NULL). We can + keep this check simple. */ + if (rtype && *rtype == 'b') { - const char *str; + const char *rev_str; - str = apr_hash_get(info->props, SVN_DAV__VERSION_NAME, - APR_HASH_KEY_STRING); - if (str) - { - ctx->commit_info->revision = SVN_STR_TO_REV(str); - } + rev_str = apr_hash_get(attrs, "revision", APR_HASH_KEY_STRING); + if (rev_str) + merge_ctx->commit_info->revision = SVN_STR_TO_REV(rev_str); else - { - ctx->commit_info->revision = SVN_INVALID_REVNUM; - } + merge_ctx->commit_info->revision = SVN_INVALID_REVNUM; - ctx->commit_info->date = - apr_pstrdup(ctx->pool, - apr_hash_get(info->props, SVN_DAV__CREATIONDATE, - APR_HASH_KEY_STRING)); - - ctx->commit_info->author = - apr_pstrdup(ctx->pool, - apr_hash_get(info->props, "creator-displayname", - APR_HASH_KEY_STRING)); - - ctx->commit_info->post_commit_err = - apr_pstrdup(ctx->pool, - apr_hash_get(info->props, + merge_ctx->commit_info->date = + apr_pstrdup(merge_ctx->pool, + apr_hash_get(attrs, "date", APR_HASH_KEY_STRING)); + + merge_ctx->commit_info->author = + apr_pstrdup(merge_ctx->pool, + apr_hash_get(attrs, "author", APR_HASH_KEY_STRING)); + + merge_ctx->commit_info->post_commit_err = + apr_pstrdup(merge_ctx->pool, + apr_hash_get(attrs, "post-commit-err", APR_HASH_KEY_STRING)); } else { const char *href; - href = apr_hash_get(info->props, "href", APR_HASH_KEY_STRING); - if (! svn_urlpath__skip_ancestor(ctx->merge_url, href)) - { - return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL, - _("A MERGE response for '%s' is not " - "a child of the destination ('%s')"), - href, ctx->merge_url); - } + href = svn_urlpath__skip_ancestor( + merge_ctx->merge_url, + apr_hash_get(attrs, "href", APR_HASH_KEY_STRING)); + + if (href == NULL) + return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL, + _("A MERGE response for '%s' is not " + "a child of the destination ('%s')"), + href, merge_ctx->merge_url); /* We now need to dive all the way into the WC to update the - * base VCC url. - */ - if ((! SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(ctx->session)) - && ctx->session->wc_callbacks->push_wc_prop) + base VCC url. */ + if (!SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(merge_ctx->session) + && merge_ctx->session->wc_callbacks->push_wc_prop) { - svn_string_t checked_in_str; const char *checked_in; + svn_string_t checked_in_str; - /* From the above check, we know that CTX->MERGE_URL is - an ancestor of HREF. All that remains is to - determine if HREF is the same as CTX->MERGE_URL, or -- - if not -- its relative value as a child thereof. */ - href = svn_urlpath__skip_ancestor(ctx->merge_url, href); - - checked_in = apr_hash_get(info->props, "checked-in", - APR_HASH_KEY_STRING); + checked_in = apr_hash_get(attrs, + "checked-in", APR_HASH_KEY_STRING); checked_in_str.data = checked_in; checked_in_str.len = strlen(checked_in); - SVN_ERR(ctx->session->wc_callbacks->push_wc_prop( - ctx->session->wc_callback_baton, href, - SVN_RA_SERF__WC_CHECKED_IN_URL, &checked_in_str, info->pool)); + SVN_ERR(merge_ctx->session->wc_callbacks->push_wc_prop( + merge_ctx->session->wc_callback_baton, + href, + SVN_RA_SERF__WC_CHECKED_IN_URL, + &checked_in_str, + scratch_pool)); } } - - svn_ra_serf__xml_pop_state(parser); - } - else if (state == PROPSTAT && - strcmp(name.name, "propstat") == 0) - { - svn_ra_serf__xml_pop_state(parser); } - else if (state == PROP && - strcmp(name.name, "prop") == 0) + else if (leaving_state == BASELINE) { - svn_ra_serf__xml_pop_state(parser); + svn_ra_serf__xml_note(xes, RESPONSE, "resourcetype", "baseline"); } - else if (state == RESOURCE_TYPE && - strcmp(name.name, "resourcetype") == 0) + else if (leaving_state == COLLECTION) { - svn_ra_serf__xml_pop_state(parser); + svn_ra_serf__xml_note(xes, RESPONSE, "resourcetype", "collection"); } - else if (state == IGNORE_PROP_NAME || state == NEED_PROP_NAME) - { - svn_ra_serf__xml_pop_state(parser); - } - else if (state == PROP_VAL) + else { - const char *value; + const char *name; + const char *value = cdata->data; - if (!info->prop_name) + if (leaving_state == HREF) { - /* ### gstein sez: dunno what this is about. */ - info->prop_name = apr_pstrdup(info->pool, name.name); + name = "href"; + value = svn_urlpath__canonicalize(value, scratch_pool); } - - if (strcmp(info->prop_name, "href") == 0) - value = svn_urlpath__canonicalize(info->prop_value->data, info->pool); + else if (leaving_state == CHECKED_IN) + { + name = "checked-in"; + value = svn_urlpath__canonicalize(value, scratch_pool); + } + else if (leaving_state == VERSION_NAME) + name = "revision"; + else if (leaving_state == DATE) + name = "date"; + else if (leaving_state == AUTHOR) + name = "author"; + else if (leaving_state == POST_COMMIT_ERR) + name = "post-commit-err"; else - value = apr_pstrmemdup(info->pool, - info->prop_value->data, info->prop_value->len); - - /* Set our property. */ - apr_hash_set(info->props, info->prop_name, APR_HASH_KEY_STRING, - value); - - info->prop_ns = NULL; - info->prop_name = NULL; - svn_stringbuf_setempty(info->prop_value); + SVN_ERR_MALFUNCTION(); - svn_ra_serf__xml_pop_state(parser); + svn_ra_serf__xml_note(xes, RESPONSE, name, value); } return SVN_NO_ERROR; } -static svn_error_t * -cdata_merge(svn_ra_serf__xml_parser_t *parser, - const char *data, - apr_size_t len, - apr_pool_t *scratch_pool) -{ - svn_ra_serf__merge_context_t *ctx = parser->user_data; - merge_state_e state; - merge_info_t *info; - - UNUSED_CTX(ctx); - - state = parser->state->current_state; - info = parser->state->private; - - if (state == PROP_VAL) - svn_stringbuf_appendbytes(info->prop_value, data, len); - - return SVN_NO_ERROR; -} static svn_error_t * setup_merge_headers(serf_bucket_t *headers, void *baton, apr_pool_t *pool) { - svn_ra_serf__merge_context_t *ctx = baton; + merge_context_t *ctx = baton; if (!ctx->keep_locks) { @@ -465,7 +334,7 @@ create_merge_body(serf_bucket_t **bkt, serf_bucket_alloc_t *alloc, apr_pool_t *pool) { - svn_ra_serf__merge_context_t *ctx = baton; + merge_context_t *ctx = baton; serf_bucket_t *body_bkt; body_bkt = serf_bucket_aggregate_create(alloc); @@ -507,21 +376,23 @@ create_merge_body(serf_bucket_t **bkt, svn_error_t * -svn_ra_serf__merge_create_req(svn_ra_serf__merge_context_t **ret_ctx, - svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, - const char *merge_resource_url, - apr_hash_t *lock_tokens, - svn_boolean_t keep_locks, - apr_pool_t *pool) +svn_ra_serf__run_merge(const svn_commit_info_t **commit_info, + int *response_code, + svn_ra_serf__session_t *session, + svn_ra_serf__connection_t *conn, + const char *merge_resource_url, + apr_hash_t *lock_tokens, + svn_boolean_t keep_locks, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - svn_ra_serf__merge_context_t *merge_ctx; + merge_context_t *merge_ctx; svn_ra_serf__handler_t *handler; - svn_ra_serf__xml_parser_t *parser_ctx; + svn_ra_serf__xml_context_t *xmlctx; - merge_ctx = apr_pcalloc(pool, sizeof(*merge_ctx)); + merge_ctx = apr_pcalloc(scratch_pool, sizeof(*merge_ctx)); - merge_ctx->pool = pool; + merge_ctx->pool = result_pool; merge_ctx->session = session; merge_ctx->merge_resource_url = merge_resource_url; @@ -529,11 +400,15 @@ svn_ra_serf__merge_create_req(svn_ra_ser merge_ctx->lock_tokens = lock_tokens; merge_ctx->keep_locks = keep_locks; - merge_ctx->commit_info = svn_create_commit_info(pool); + merge_ctx->commit_info = svn_create_commit_info(result_pool); merge_ctx->merge_url = session->session_url.path; - handler = apr_pcalloc(pool, sizeof(*handler)); + xmlctx = svn_ra_serf__xml_context_create(merge_ttable, + NULL, merge_closed, NULL, + merge_ctx, + scratch_pool); + handler = svn_ra_serf__create_expat_handler(xmlctx, scratch_pool); handler->method = "MERGE"; handler->path = merge_ctx->merge_url; @@ -542,43 +417,15 @@ svn_ra_serf__merge_create_req(svn_ra_ser handler->conn = conn; handler->session = session; - parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx)); - - parser_ctx->pool = pool; - parser_ctx->user_data = merge_ctx; - parser_ctx->start = start_merge; - parser_ctx->end = end_merge; - parser_ctx->cdata = cdata_merge; - parser_ctx->done = &merge_ctx->done; - parser_ctx->status_code = &merge_ctx->status; - handler->header_delegate = setup_merge_headers; handler->header_delegate_baton = merge_ctx; - handler->response_handler = svn_ra_serf__handle_xml_parser; - handler->response_baton = parser_ctx; + merge_ctx->handler = handler; - svn_ra_serf__request_create(handler); + SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool)); - *ret_ctx = merge_ctx; + *commit_info = merge_ctx->commit_info; + *response_code = handler->sline.code; return SVN_NO_ERROR; } - -svn_boolean_t* -svn_ra_serf__merge_get_done_ptr(svn_ra_serf__merge_context_t *ctx) -{ - return &ctx->done; -} - -svn_commit_info_t* -svn_ra_serf__merge_get_commit_info(svn_ra_serf__merge_context_t *ctx) -{ - return ctx->commit_info; -} - -int -svn_ra_serf__merge_get_status(svn_ra_serf__merge_context_t *ctx) -{ - return ctx->status; -}
Modified: subversion/branches/master-passphrase/subversion/libsvn_ra_serf/mergeinfo.c URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_ra_serf/mergeinfo.c?rev=1354571&r1=1354570&r2=1354571&view=diff ============================================================================== --- subversion/branches/master-passphrase/subversion/libsvn_ra_serf/mergeinfo.c (original) +++ subversion/branches/master-passphrase/subversion/libsvn_ra_serf/mergeinfo.c Wed Jun 27 15:12:37 2012 @@ -40,7 +40,7 @@ /* The current state of our XML parsing. */ typedef enum mergeinfo_state_e { - NONE = 0, + INITIAL = 0, MERGEINFO_REPORT, MERGEINFO_ITEM, MERGEINFO_PATH, @@ -49,135 +49,88 @@ typedef enum mergeinfo_state_e { /* Baton for accumulating mergeinfo. RESULT_CATALOG stores the final mergeinfo catalog result we are going to hand back to the caller of - get_mergeinfo. curr_path and curr_info contain the value of the - CDATA from the mergeinfo items as we get them from the server. */ - + get_mergeinfo. */ typedef struct mergeinfo_context_t { apr_pool_t *pool; - svn_stringbuf_t *curr_path; - svn_stringbuf_t *curr_info; svn_mergeinfo_t result_catalog; - svn_boolean_t done; const apr_array_header_t *paths; svn_revnum_t revision; svn_mergeinfo_inheritance_t inherit; svn_boolean_t include_descendants; } mergeinfo_context_t; -static svn_error_t * -start_element(svn_ra_serf__xml_parser_t *parser, - svn_ra_serf__dav_props_t name, - const char **attrs, - apr_pool_t *scratch_pool) -{ - mergeinfo_context_t *mergeinfo_ctx = parser->user_data; - mergeinfo_state_e state; - state = parser->state->current_state; - if (state == NONE && strcmp(name.name, SVN_DAV__MERGEINFO_REPORT) == 0) - { - svn_ra_serf__xml_push_state(parser, MERGEINFO_REPORT); - } - else if (state == MERGEINFO_REPORT && - strcmp(name.name, SVN_DAV__MERGEINFO_ITEM) == 0) - { - svn_ra_serf__xml_push_state(parser, MERGEINFO_ITEM); - svn_stringbuf_setempty(mergeinfo_ctx->curr_path); - svn_stringbuf_setempty(mergeinfo_ctx->curr_info); - } - else if (state == MERGEINFO_ITEM && - strcmp(name.name, SVN_DAV__MERGEINFO_PATH) == 0) - { - svn_ra_serf__xml_push_state(parser, MERGEINFO_PATH); - } - else if (state == MERGEINFO_ITEM && - strcmp(name.name, SVN_DAV__MERGEINFO_INFO) == 0) - { - svn_ra_serf__xml_push_state(parser, MERGEINFO_INFO); - } - return SVN_NO_ERROR; -} +#define D_ "DAV:" +#define S_ SVN_XML_NAMESPACE +static const svn_ra_serf__xml_transition_t mergeinfo_ttable[] = { + { INITIAL, S_, SVN_DAV__MERGEINFO_REPORT, MERGEINFO_REPORT, + FALSE, { NULL }, FALSE }, + + { MERGEINFO_REPORT, S_, SVN_DAV__MERGEINFO_ITEM, MERGEINFO_ITEM, + FALSE, { NULL }, TRUE }, + + { MERGEINFO_ITEM, S_, SVN_DAV__MERGEINFO_PATH, MERGEINFO_PATH, + TRUE, { NULL }, TRUE }, + + { MERGEINFO_ITEM, S_, SVN_DAV__MERGEINFO_INFO, MERGEINFO_INFO, + TRUE, { NULL }, TRUE }, + + { 0 } +}; + +/* Conforms to svn_ra_serf__xml_closed_t */ static svn_error_t * -end_element(svn_ra_serf__xml_parser_t *parser, - svn_ra_serf__dav_props_t name, - apr_pool_t *scratch_pool) +mergeinfo_closed(svn_ra_serf__xml_estate_t *xes, + void *baton, + int leaving_state, + const svn_string_t *cdata, + apr_hash_t *attrs, + apr_pool_t *scratch_pool) { - mergeinfo_context_t *mergeinfo_ctx = parser->user_data; - mergeinfo_state_e state; - - state = parser->state->current_state; + mergeinfo_context_t *mergeinfo_ctx = baton; - if (state == MERGEINFO_REPORT && - strcmp(name.name, SVN_DAV__MERGEINFO_REPORT) == 0) + if (leaving_state == MERGEINFO_ITEM) { - svn_ra_serf__xml_pop_state(parser); - } - else if (state == MERGEINFO_ITEM - && strcmp(name.name, SVN_DAV__MERGEINFO_ITEM) == 0) - { - if (mergeinfo_ctx->curr_info && mergeinfo_ctx->curr_path) + /* Placed here from the child elements. */ + const char *path = apr_hash_get(attrs, "path", APR_HASH_KEY_STRING); + const char *info = apr_hash_get(attrs, "info", APR_HASH_KEY_STRING); + + if (path != NULL && info != NULL) { svn_mergeinfo_t path_mergeinfo; - const char *path; - SVN_ERR_ASSERT(mergeinfo_ctx->curr_path->data); - path = apr_pstrdup(mergeinfo_ctx->pool, - mergeinfo_ctx->curr_path->data); - SVN_ERR(svn_mergeinfo_parse(&path_mergeinfo, - mergeinfo_ctx->curr_info->data, - mergeinfo_ctx->pool)); /* Correct for naughty servers that send "relative" paths with leading slashes! */ + if (path[0] == '/') + ++path; + + SVN_ERR(svn_mergeinfo_parse(&path_mergeinfo, info, + mergeinfo_ctx->pool)); + apr_hash_set(mergeinfo_ctx->result_catalog, - path[0] == '/' ? path + 1 : path, - APR_HASH_KEY_STRING, path_mergeinfo); + apr_pstrdup(mergeinfo_ctx->pool, path), + APR_HASH_KEY_STRING, + path_mergeinfo); } - svn_ra_serf__xml_pop_state(parser); - } - else if (state == MERGEINFO_PATH - && strcmp(name.name, SVN_DAV__MERGEINFO_PATH) == 0) - { - svn_ra_serf__xml_pop_state(parser); } - else if (state == MERGEINFO_INFO - && strcmp(name.name, SVN_DAV__MERGEINFO_INFO) == 0) - { - svn_ra_serf__xml_pop_state(parser); - } - return SVN_NO_ERROR; -} - - -static svn_error_t * -cdata_handler(svn_ra_serf__xml_parser_t *parser, - const char *data, - apr_size_t len, - apr_pool_t *scratch_pool) -{ - mergeinfo_context_t *mergeinfo_ctx = parser->user_data; - mergeinfo_state_e state; - - state = parser->state->current_state; - switch (state) + else { - case MERGEINFO_PATH: - if (mergeinfo_ctx->curr_path) - svn_stringbuf_appendbytes(mergeinfo_ctx->curr_path, data, len); - break; - - case MERGEINFO_INFO: - if (mergeinfo_ctx->curr_info) - svn_stringbuf_appendbytes(mergeinfo_ctx->curr_info, data, len); - break; + SVN_ERR_ASSERT(leaving_state == MERGEINFO_PATH + || leaving_state == MERGEINFO_INFO); - default: - break; + /* Stash the value onto the parent MERGEINFO_ITEM. */ + svn_ra_serf__xml_note(xes, MERGEINFO_ITEM, + leaving_state == MERGEINFO_PATH + ? "path" + : "info", + cdata->data); } return SVN_NO_ERROR; } + static svn_error_t * create_mergeinfo_body(serf_bucket_t **bkt, void *baton, @@ -229,8 +182,6 @@ create_mergeinfo_body(serf_bucket_t **bk return SVN_NO_ERROR; } -/* Request a mergeinfo-report from the URL attached to SESSION, - and fill in the MERGEINFO hash with the results. */ svn_error_t * svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session, svn_mergeinfo_catalog_t *catalog, @@ -241,34 +192,32 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio apr_pool_t *pool) { svn_error_t *err, *err2; - int status_code; - mergeinfo_context_t *mergeinfo_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; - svn_ra_serf__xml_parser_t *parser_ctx; - const char *relative_url, *basecoll_url; + svn_ra_serf__xml_context_t *xmlctx; const char *path; *catalog = NULL; - SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session, - NULL, NULL, revision, NULL, pool)); - - path = svn_path_url_add_component2(basecoll_url, relative_url, pool); + SVN_ERR(svn_ra_serf__get_stable_url(&path, NULL /* latest_revnum */, + session, NULL /* conn */, + NULL /* url */, revision, + pool, pool)); mergeinfo_ctx = apr_pcalloc(pool, sizeof(*mergeinfo_ctx)); mergeinfo_ctx->pool = pool; - mergeinfo_ctx->curr_path = svn_stringbuf_create_empty(pool); - mergeinfo_ctx->curr_info = svn_stringbuf_create_empty(pool); - mergeinfo_ctx->done = FALSE; mergeinfo_ctx->result_catalog = apr_hash_make(pool); mergeinfo_ctx->paths = paths; mergeinfo_ctx->revision = revision; mergeinfo_ctx->inherit = inherit; mergeinfo_ctx->include_descendants = include_descendants; - handler = apr_pcalloc(pool, sizeof(*handler)); + xmlctx = svn_ra_serf__xml_context_create(mergeinfo_ttable, + NULL, mergeinfo_closed, NULL, + mergeinfo_ctx, + pool); + handler = svn_ra_serf__create_expat_handler(xmlctx, pool); handler->method = "REPORT"; handler->path = path; @@ -278,25 +227,10 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio handler->body_delegate_baton = mergeinfo_ctx; handler->body_type = "text/xml"; - parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx)); - - parser_ctx->pool = pool; - parser_ctx->user_data = mergeinfo_ctx; - parser_ctx->start = start_element; - parser_ctx->end = end_element; - parser_ctx->cdata = cdata_handler; - parser_ctx->done = &mergeinfo_ctx->done; - parser_ctx->status_code = &status_code; - - handler->response_handler = svn_ra_serf__handle_xml_parser; - handler->response_baton = parser_ctx; - - svn_ra_serf__request_create(handler); - - err = svn_ra_serf__context_run_wait(&mergeinfo_ctx->done, session, pool); + err = svn_ra_serf__context_run_one(handler, pool); - err2 = svn_ra_serf__error_on_status(status_code, handler->path, - parser_ctx->location); + err2 = svn_ra_serf__error_on_status(handler->sline.code, handler->path, + handler->location); if (err2) { svn_error_clear(err); @@ -305,7 +239,7 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio SVN_ERR(err); - if (mergeinfo_ctx->done && apr_hash_count(mergeinfo_ctx->result_catalog)) + if (handler->done && apr_hash_count(mergeinfo_ctx->result_catalog)) *catalog = mergeinfo_ctx->result_catalog; return SVN_NO_ERROR; Modified: subversion/branches/master-passphrase/subversion/libsvn_ra_serf/options.c URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_ra_serf/options.c?rev=1354571&r1=1354570&r2=1354571&view=diff ============================================================================== --- subversion/branches/master-passphrase/subversion/libsvn_ra_serf/options.c (original) +++ subversion/branches/master-passphrase/subversion/libsvn_ra_serf/options.c Wed Jun 27 15:12:37 2012 @@ -48,165 +48,68 @@ /* * This enum represents the current state of our XML parsing for an OPTIONS. */ -typedef enum options_state_e { +enum options_state_e { + INITIAL = 0, OPTIONS, ACTIVITY_COLLECTION, HREF -} options_state_e; - -typedef struct options_state_list_t { - /* The current state that we are in now. */ - options_state_e state; - - /* The previous state we were in. */ - struct options_state_list_t *prev; -} options_state_list_t; +}; -struct svn_ra_serf__options_context_t { +typedef struct options_context_t { /* pool to allocate memory from */ apr_pool_t *pool; - /* Buffer for the activity-collection */ - svn_stringbuf_t *acbuf; - svn_boolean_t collect_cdata; - - /* Current state we're in */ - options_state_list_t *state; - options_state_list_t *free_state; - - /* HTTP Status code */ - int status_code; - - /* are we done? */ - svn_boolean_t done; + /* Have we extracted options values from the headers already? */ + svn_boolean_t headers_processed; svn_ra_serf__session_t *session; svn_ra_serf__connection_t *conn; + svn_ra_serf__handler_t *handler; - const char *path; + svn_ra_serf__response_handler_t inner_handler; + void *inner_baton; const char *activity_collection; svn_revnum_t youngest_rev; - serf_response_acceptor_t acceptor; - serf_response_handler_t handler; - svn_ra_serf__xml_parser_t *parser_ctx; +} options_context_t; -}; +#define D_ "DAV:" +#define S_ SVN_XML_NAMESPACE +static const svn_ra_serf__xml_transition_t options_ttable[] = { + { INITIAL, D_, "options-response", OPTIONS, + FALSE, { NULL }, FALSE }, -static void -push_state(svn_ra_serf__options_context_t *options_ctx, options_state_e state) -{ - options_state_list_t *new_state; + { OPTIONS, D_, "activity-collection-set", ACTIVITY_COLLECTION, + FALSE, { NULL }, FALSE }, - if (!options_ctx->free_state) - { - new_state = apr_palloc(options_ctx->pool, sizeof(*options_ctx->state)); - } - else - { - new_state = options_ctx->free_state; - options_ctx->free_state = options_ctx->free_state->prev; - } - new_state->state = state; + { ACTIVITY_COLLECTION, D_, "href", HREF, + TRUE, { NULL }, TRUE }, - /* Add it to the state chain. */ - new_state->prev = options_ctx->state; - options_ctx->state = new_state; -} - -static void pop_state(svn_ra_serf__options_context_t *options_ctx) -{ - options_state_list_t *free_state; - free_state = options_ctx->state; - /* advance the current state */ - options_ctx->state = options_ctx->state->prev; - free_state->prev = options_ctx->free_state; - options_ctx->free_state = free_state; -} - -static svn_error_t * -start_options(svn_ra_serf__xml_parser_t *parser, - svn_ra_serf__dav_props_t name, - const char **attrs, - apr_pool_t *scratch_pool) -{ - svn_ra_serf__options_context_t *options_ctx = parser->user_data; - - if (!options_ctx->state && strcmp(name.name, "options-response") == 0) - { - push_state(options_ctx, OPTIONS); - } - else if (!options_ctx->state) - { - /* Nothing to do. */ - return SVN_NO_ERROR; - } - else if (options_ctx->state->state == OPTIONS && - strcmp(name.name, "activity-collection-set") == 0) - { - push_state(options_ctx, ACTIVITY_COLLECTION); - } - else if (options_ctx->state->state == ACTIVITY_COLLECTION && - strcmp(name.name, "href") == 0) - { - options_ctx->collect_cdata = TRUE; - push_state(options_ctx, HREF); - } + { 0 } +}; - return SVN_NO_ERROR; -} +/* Conforms to svn_ra_serf__xml_closed_t */ static svn_error_t * -end_options(svn_ra_serf__xml_parser_t *parser, - svn_ra_serf__dav_props_t name, - apr_pool_t *scratch_pool) +options_closed(svn_ra_serf__xml_estate_t *xes, + void *baton, + int leaving_state, + const svn_string_t *cdata, + apr_hash_t *attrs, + apr_pool_t *scratch_pool) { - svn_ra_serf__options_context_t *options_ctx = parser->user_data; - options_state_list_t *cur_state; - - if (!options_ctx->state) - { - return SVN_NO_ERROR; - } + options_context_t *opt_ctx = baton; - cur_state = options_ctx->state; + SVN_ERR_ASSERT(leaving_state == HREF); + SVN_ERR_ASSERT(cdata != NULL); - if (cur_state->state == OPTIONS && - strcmp(name.name, "options-response") == 0) - { - pop_state(options_ctx); - } - else if (cur_state->state == ACTIVITY_COLLECTION && - strcmp(name.name, "activity-collection-set") == 0) - { - pop_state(options_ctx); - } - else if (cur_state->state == HREF && - strcmp(name.name, "href") == 0) - { - options_ctx->collect_cdata = FALSE; - options_ctx->activity_collection = - svn_urlpath__canonicalize(options_ctx->acbuf->data, options_ctx->pool); - pop_state(options_ctx); - } + opt_ctx->activity_collection = svn_urlpath__canonicalize(cdata->data, + opt_ctx->pool); return SVN_NO_ERROR; } -static svn_error_t * -cdata_options(svn_ra_serf__xml_parser_t *parser, - const char *data, - apr_size_t len, - apr_pool_t *scratch_pool) -{ - svn_ra_serf__options_context_t *ctx = parser->user_data; - - if (ctx->collect_cdata) - svn_stringbuf_appendbytes(ctx->acbuf, data, len); - - return SVN_NO_ERROR; -} static svn_error_t * create_options_body(serf_bucket_t **body_bkt, @@ -227,47 +130,17 @@ create_options_body(serf_bucket_t **body return SVN_NO_ERROR; } -svn_boolean_t* -svn_ra_serf__get_options_done_ptr(svn_ra_serf__options_context_t *ctx) -{ - return &ctx->done; -} - -const char * -svn_ra_serf__options_get_activity_collection(svn_ra_serf__options_context_t *ctx) -{ - return ctx->activity_collection; -} - -svn_revnum_t -svn_ra_serf__options_get_youngest_rev(svn_ra_serf__options_context_t *ctx) -{ - return ctx->youngest_rev; -} - -/* Context for both options_response_handler() and capabilities callback. */ -struct options_response_ctx_t { - /* Baton for __handle_xml_parser() */ - svn_ra_serf__xml_parser_t *parser_ctx; - - /* Session into which we'll store server capabilities */ - svn_ra_serf__session_t *session; - - /* For temporary work only. */ - apr_pool_t *pool; -}; - /* We use these static pointers so we can employ pointer comparison * of our capabilities hash members instead of strcmp()ing all over * the place. */ /* Both server and repository support the capability. */ -static const char *capability_yes = "yes"; +static const char *const capability_yes = "yes"; /* Either server or repository does not support the capability. */ -static const char *capability_no = "no"; +static const char *const capability_no = "no"; /* Server supports the capability, but don't yet know if repository does. */ -static const char *capability_server_yes = "server-yes"; +static const char *const capability_server_yes = "server-yes"; /* This implements serf_bucket_headers_do_callback_fn_t. @@ -277,7 +150,8 @@ capabilities_headers_iterator_callback(v const char *key, const char *val) { - struct options_response_ctx_t *orc = baton; + options_context_t *opt_ctx = baton; + svn_ra_serf__session_t *session = opt_ctx->session; if (svn_cstring_casecmp(key, "dav") == 0) { @@ -285,7 +159,8 @@ capabilities_headers_iterator_callback(v DAV: version-control,checkout,working-resource DAV: merge,baseline,activity,version-controlled-collection DAV: http://subversion.tigris.org/xmlns/dav/svn/depth */ - apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE, orc->pool); + apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE, + opt_ctx->pool); /* Right now we only have a few capabilities to detect, so just seek for them directly. This could be written slightly more @@ -294,33 +169,35 @@ capabilities_headers_iterator_callback(v if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals)) { - apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_DEPTH, - APR_HASH_KEY_STRING, capability_yes); + apr_hash_set(session->capabilities, + SVN_RA_CAPABILITY_DEPTH, APR_HASH_KEY_STRING, + capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals)) { /* The server doesn't know what repository we're referring to, so it can't just say capability_yes. */ - apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_MERGEINFO, - APR_HASH_KEY_STRING, capability_server_yes); + apr_hash_set(session->capabilities, + SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING, + capability_server_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals)) { - apr_hash_set(orc->session->capabilities, - SVN_RA_CAPABILITY_LOG_REVPROPS, - APR_HASH_KEY_STRING, capability_yes); + apr_hash_set(session->capabilities, + SVN_RA_CAPABILITY_LOG_REVPROPS, APR_HASH_KEY_STRING, + capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals)) { - apr_hash_set(orc->session->capabilities, - SVN_RA_CAPABILITY_ATOMIC_REVPROPS, - APR_HASH_KEY_STRING, capability_yes); + apr_hash_set(session->capabilities, + SVN_RA_CAPABILITY_ATOMIC_REVPROPS, APR_HASH_KEY_STRING, + capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals)) { - apr_hash_set(orc->session->capabilities, - SVN_RA_CAPABILITY_PARTIAL_REPLAY, - APR_HASH_KEY_STRING, capability_yes); + apr_hash_set(session->capabilities, + SVN_RA_CAPABILITY_PARTIAL_REPLAY, APR_HASH_KEY_STRING, + capability_yes); } } @@ -329,14 +206,12 @@ capabilities_headers_iterator_callback(v { if (svn_cstring_casecmp(key, SVN_DAV_ROOT_URI_HEADER) == 0) { - orc->session->repos_root = orc->session->session_url; - orc->session->repos_root.path = apr_pstrdup(orc->session->pool, val); - orc->session->repos_root_str = + session->repos_root = session->session_url; + session->repos_root.path = apr_pstrdup(session->pool, val); + session->repos_root_str = svn_urlpath__canonicalize( - apr_uri_unparse(orc->session->pool, - &orc->session->repos_root, - 0), - orc->session->pool); + apr_uri_unparse(session->pool, &session->repos_root, 0), + session->pool); } else if (svn_cstring_casecmp(key, SVN_DAV_ME_RESOURCE_HEADER) == 0) { @@ -345,44 +220,42 @@ capabilities_headers_iterator_callback(v if (!(ignore_v2_env_var && apr_strnatcasecmp(ignore_v2_env_var, "yes") == 0)) - orc->session->me_resource = apr_pstrdup(orc->session->pool, val); + session->me_resource = apr_pstrdup(session->pool, val); #else - orc->session->me_resource = apr_pstrdup(orc->session->pool, val); + session->me_resource = apr_pstrdup(session->pool, val); #endif } else if (svn_cstring_casecmp(key, SVN_DAV_REV_STUB_HEADER) == 0) { - orc->session->rev_stub = apr_pstrdup(orc->session->pool, val); + session->rev_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_REV_ROOT_STUB_HEADER) == 0) { - orc->session->rev_root_stub = apr_pstrdup(orc->session->pool, val); + session->rev_root_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_TXN_STUB_HEADER) == 0) { - orc->session->txn_stub = apr_pstrdup(orc->session->pool, val); + session->txn_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_TXN_ROOT_STUB_HEADER) == 0) { - orc->session->txn_root_stub = apr_pstrdup(orc->session->pool, val); + session->txn_root_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_STUB_HEADER) == 0) { - orc->session->vtxn_stub = apr_pstrdup(orc->session->pool, val); + session->vtxn_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_ROOT_STUB_HEADER) == 0) { - orc->session->vtxn_root_stub = apr_pstrdup(orc->session->pool, val); + session->vtxn_root_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_REPOS_UUID_HEADER) == 0) { - orc->session->uuid = apr_pstrdup(orc->session->pool, val); + session->uuid = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_YOUNGEST_REV_HEADER) == 0) { - struct svn_ra_serf__options_context_t *user_data = - orc->parser_ctx->user_data; - user_data->youngest_rev = SVN_STR_TO_REV(val); + opt_ctx->youngest_rev = SVN_STR_TO_REV(val); } } @@ -391,7 +264,7 @@ capabilities_headers_iterator_callback(v /* A custom serf_response_handler_t which is mostly a wrapper around - svn_ra_serf__handle_xml_parser -- it just notices OPTIONS response + the expat-based response handler -- it just notices OPTIONS response headers first, before handing off to the xml parser. Implements svn_ra_serf__response_handler_t */ static svn_error_t * @@ -400,88 +273,117 @@ options_response_handler(serf_request_t void *baton, apr_pool_t *pool) { - struct options_response_ctx_t *orc = baton; - serf_bucket_t *hdrs = serf_bucket_response_get_headers(response); + options_context_t *opt_ctx = baton; + + if (!opt_ctx->headers_processed) + { + svn_ra_serf__session_t *session = opt_ctx->session; + serf_bucket_t *hdrs = serf_bucket_response_get_headers(response); - /* Start out assuming all capabilities are unsupported. */ - apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY, - APR_HASH_KEY_STRING, capability_no); - apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_DEPTH, - APR_HASH_KEY_STRING, capability_no); - apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_MERGEINFO, - APR_HASH_KEY_STRING, capability_no); - apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS, - APR_HASH_KEY_STRING, capability_no); - apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS, - APR_HASH_KEY_STRING, capability_no); + /* Start out assuming all capabilities are unsupported. */ + apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY, + APR_HASH_KEY_STRING, capability_no); + apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_DEPTH, + APR_HASH_KEY_STRING, capability_no); + apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO, + APR_HASH_KEY_STRING, capability_no); + apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS, + APR_HASH_KEY_STRING, capability_no); + apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS, + APR_HASH_KEY_STRING, capability_no); + + /* Then see which ones we can discover. */ + serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback, + opt_ctx); - /* Then see which ones we can discover. */ - serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback, orc); + opt_ctx->headers_processed = TRUE; + } /* Execute the 'real' response handler to XML-parse the repsonse body. */ - return svn_ra_serf__handle_xml_parser(request, response, - orc->parser_ctx, pool); + return opt_ctx->inner_handler(request, response, opt_ctx->inner_baton, pool); } -svn_error_t * -svn_ra_serf__create_options_req(svn_ra_serf__options_context_t **opt_ctx, - svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, - const char *path, - apr_pool_t *pool) +static svn_error_t * +create_options_req(options_context_t **opt_ctx, + svn_ra_serf__session_t *session, + svn_ra_serf__connection_t *conn, + apr_pool_t *pool) { - svn_ra_serf__options_context_t *new_ctx; + options_context_t *new_ctx; + svn_ra_serf__xml_context_t *xmlctx; svn_ra_serf__handler_t *handler; - svn_ra_serf__xml_parser_t *parser_ctx; - struct options_response_ctx_t *options_response_ctx; new_ctx = apr_pcalloc(pool, sizeof(*new_ctx)); - new_ctx->pool = pool; - - new_ctx->acbuf = svn_stringbuf_create_empty(pool); - - new_ctx->path = path; - new_ctx->youngest_rev = SVN_INVALID_REVNUM; - new_ctx->session = session; new_ctx->conn = conn; - handler = apr_pcalloc(pool, sizeof(*handler)); + new_ctx->youngest_rev = SVN_INVALID_REVNUM; + + xmlctx = svn_ra_serf__xml_context_create(options_ttable, + NULL, options_closed, NULL, + new_ctx, + pool); + handler = svn_ra_serf__create_expat_handler(xmlctx, pool); handler->method = "OPTIONS"; - handler->path = path; + handler->path = session->session_url.path; handler->body_delegate = create_options_body; handler->body_type = "text/xml"; handler->conn = conn; handler->session = session; - parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx)); - - parser_ctx->pool = pool; - parser_ctx->user_data = new_ctx; - parser_ctx->start = start_options; - parser_ctx->end = end_options; - parser_ctx->cdata = cdata_options; - parser_ctx->done = &new_ctx->done; - parser_ctx->status_code = &new_ctx->status_code; - - options_response_ctx = apr_pcalloc(pool, sizeof(*options_response_ctx)); - options_response_ctx->parser_ctx = parser_ctx; - options_response_ctx->session = session; - options_response_ctx->pool = pool; + new_ctx->handler = handler; + new_ctx->inner_handler = handler->response_handler; + new_ctx->inner_baton = handler->response_baton; handler->response_handler = options_response_handler; - handler->response_baton = options_response_ctx; + handler->response_baton = new_ctx; + + *opt_ctx = new_ctx; + + return SVN_NO_ERROR; +} + - svn_ra_serf__request_create(handler); +svn_error_t * +svn_ra_serf__v2_get_youngest_revnum(svn_revnum_t *youngest, + svn_ra_serf__connection_t *conn, + apr_pool_t *scratch_pool) +{ + svn_ra_serf__session_t *session = conn->session; + options_context_t *opt_ctx; - new_ctx->parser_ctx = parser_ctx; + SVN_ERR_ASSERT(SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session)); - *opt_ctx = new_ctx; + SVN_ERR(create_options_req(&opt_ctx, session, conn, scratch_pool)); + SVN_ERR(svn_ra_serf__context_run_one(opt_ctx->handler, scratch_pool)); + + *youngest = opt_ctx->youngest_rev; + + return SVN_NO_ERROR; +} + + +svn_error_t * +svn_ra_serf__v1_get_activity_collection(const char **activity_url, + svn_ra_serf__connection_t *conn, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_ra_serf__session_t *session = conn->session; + options_context_t *opt_ctx; + + SVN_ERR_ASSERT(!SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session)); + + SVN_ERR(create_options_req(&opt_ctx, session, conn, scratch_pool)); + SVN_ERR(svn_ra_serf__context_run_one(opt_ctx->handler, scratch_pool)); + + *activity_url = apr_pstrdup(result_pool, opt_ctx->activity_collection); return SVN_NO_ERROR; + } @@ -493,32 +395,29 @@ svn_ra_serf__exchange_capabilities(svn_r const char **corrected_url, apr_pool_t *pool) { - svn_ra_serf__options_context_t *opt_ctx; + options_context_t *opt_ctx; svn_error_t *err; /* This routine automatically fills in serf_sess->capabilities */ - SVN_ERR(svn_ra_serf__create_options_req(&opt_ctx, serf_sess, - serf_sess->conns[0], - serf_sess->session_url.path, pool)); + SVN_ERR(create_options_req(&opt_ctx, serf_sess, serf_sess->conns[0], pool)); - err = svn_ra_serf__context_run_wait( - svn_ra_serf__get_options_done_ptr(opt_ctx), serf_sess, pool); + err = svn_ra_serf__context_run_one(opt_ctx->handler, pool); /* If our caller cares about server redirections, and our response carries such a thing, report as much. We'll disregard ERR -- it's most likely just a complaint about the response body not successfully parsing as XML or somesuch. */ - if (corrected_url && (opt_ctx->status_code == 301)) + if (corrected_url && (opt_ctx->handler->sline.code == 301)) { svn_error_clear(err); - *corrected_url = opt_ctx->parser_ctx->location; + *corrected_url = opt_ctx->handler->location; return SVN_NO_ERROR; } return svn_error_compose_create( - svn_ra_serf__error_on_status(opt_ctx->status_code, + svn_ra_serf__error_on_status(opt_ctx->handler->sline.code, serf_sess->session_url.path, - opt_ctx->parser_ctx->location), + opt_ctx->handler->location), err); } @@ -551,9 +450,7 @@ svn_ra_serf__has_capability(svn_ra_sessi cap_result = apr_hash_get(serf_sess->capabilities, capability, APR_HASH_KEY_STRING); - /* Some capabilities depend on the repository as well as the server. - NOTE: svn_ra_neon__has_capability() has a very similar code block. If - you change something here, check there as well. */ + /* Some capabilities depend on the repository as well as the server. */ if (cap_result == capability_server_yes) { if (strcmp(capability, SVN_RA_CAPABILITY_MERGEINFO) == 0)
