diff options
Diffstat (limited to 'subversion/libsvn_ra_serf/log.c')
-rw-r--r-- | subversion/libsvn_ra_serf/log.c | 599 |
1 files changed, 235 insertions, 364 deletions
diff --git a/subversion/libsvn_ra_serf/log.c b/subversion/libsvn_ra_serf/log.c index cd6a6b2..02f2f29 100644 --- a/subversion/libsvn_ra_serf/log.c +++ b/subversion/libsvn_ra_serf/log.c @@ -24,11 +24,9 @@ #include <apr_uri.h> - -#include <expat.h> - #include <serf.h> +#include "svn_hash.h" #include "svn_pools.h" #include "svn_ra.h" #include "svn_dav.h" @@ -39,6 +37,8 @@ #include "svn_props.h" #include "private/svn_dav_protocol.h" +#include "private/svn_string_private.h" +#include "private/svn_subr_private.h" #include "svn_private_config.h" #include "ra_serf.h" @@ -48,8 +48,8 @@ /* * This enum represents the current state of our XML parsing for a REPORT. */ -typedef enum log_state_e { - NONE = 0, +enum { + INITIAL = 0, REPORT, ITEM, VERSION, @@ -63,27 +63,7 @@ typedef enum log_state_e { DELETED_PATH, MODIFIED_PATH, SUBTRACTIVE_MERGE -} log_state_e; - -typedef struct log_info_t { - apr_pool_t *pool; - - /* The currently collected value as we build it up, and its wire - * encoding (if any). - */ - const char *tmp; - apr_size_t tmp_len; - const char *tmp_encoding; - - /* Temporary change path - ultimately inserted into changed_paths hash. */ - svn_log_changed_path2_t *tmp_path; - - /* Log information */ - svn_log_entry_t *log_entry; - - /* Place to hold revprop name. */ - const char *revprop_name; -} log_info_t; +}; typedef struct log_context_t { apr_pool_t *pool; @@ -100,9 +80,11 @@ typedef struct log_context_t { int nest_level; /* used to track mergeinfo nesting levels */ int count; /* only incremented when nest_level == 0 */ - /* are we done? */ - svn_boolean_t done; - int status_code; + /* Collect information for storage into a log entry. Most of the entry + members are collected by individual states. revprops and paths are + N datapoints per entry. */ + apr_hash_t *collect_revprops; + apr_hash_t *collect_paths; /* log receiver function and baton */ svn_log_entry_receiver_t receiver; @@ -114,406 +96,307 @@ typedef struct log_context_t { svn_boolean_t want_message; } log_context_t; - -static log_info_t * -push_state(svn_ra_serf__xml_parser_t *parser, - log_context_t *log_ctx, - log_state_e state, - const char **attrs) -{ - svn_ra_serf__xml_push_state(parser, state); +#define D_ "DAV:" +#define S_ SVN_XML_NAMESPACE +static const svn_ra_serf__xml_transition_t log_ttable[] = { + { INITIAL, S_, "log-report", REPORT, + FALSE, { NULL }, FALSE }, - if (state == ITEM) - { - log_info_t *info; - apr_pool_t *info_pool = svn_pool_create(parser->state->pool); + /* Note that we have an opener here. We need to construct a new LOG_ENTRY + to record multiple paths. */ + { REPORT, S_, "log-item", ITEM, + FALSE, { NULL }, TRUE }, - info = apr_pcalloc(info_pool, sizeof(*info)); - info->pool = info_pool; - info->log_entry = svn_log_entry_create(info_pool); + { ITEM, D_, SVN_DAV__VERSION_NAME, VERSION, + TRUE, { NULL }, TRUE }, - info->log_entry->revision = SVN_INVALID_REVNUM; + { ITEM, D_, "creator-displayname", CREATOR, + TRUE, { "?encoding", NULL }, TRUE }, - parser->state->private = info; - } + { ITEM, S_, "date", DATE, + TRUE, { "?encoding", NULL }, TRUE }, - if (state == ADDED_PATH || state == REPLACED_PATH || - state == DELETED_PATH || state == MODIFIED_PATH) - { - log_info_t *info = parser->state->private; + { ITEM, D_, "comment", COMMENT, + TRUE, { "?encoding", NULL }, TRUE }, - if (!info->log_entry->changed_paths2) - { - info->log_entry->changed_paths2 = apr_hash_make(info->pool); - info->log_entry->changed_paths = info->log_entry->changed_paths2; - } + { ITEM, S_, "revprop", REVPROP, + TRUE, { "name", "?encoding", NULL }, TRUE }, - info->tmp_path = svn_log_changed_path2_create(info->pool); - info->tmp_path->copyfrom_rev = SVN_INVALID_REVNUM; - } + { ITEM, S_, "has-children", HAS_CHILDREN, + FALSE, { NULL }, TRUE }, - if (state == CREATOR || state == DATE || state == COMMENT - || state == REVPROP) - { - log_info_t *info = parser->state->private; + { ITEM, S_, "subtractive-merge", SUBTRACTIVE_MERGE, + FALSE, { NULL }, TRUE }, - info->tmp_encoding = svn_xml_get_attr_value("encoding", attrs); - if (info->tmp_encoding) - info->tmp_encoding = apr_pstrdup(info->pool, info->tmp_encoding); + { ITEM, S_, "added-path", ADDED_PATH, + TRUE, { "?node-kind", "?text-mods", "?prop-mods", + "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE }, - if (!info->log_entry->revprops) - { - info->log_entry->revprops = apr_hash_make(info->pool); - } - } + { ITEM, S_, "replaced-path", REPLACED_PATH, + TRUE, { "?node-kind", "?text-mods", "?prop-mods", + "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE }, - return parser->state->private; -} + { ITEM, S_, "deleted-path", DELETED_PATH, + TRUE, { "?node-kind", "?text-mods", "?prop-mods", NULL }, TRUE }, -/* Helper function to parse the common arguments availabe in ATTRS into CHANGE. */ -static svn_error_t * -read_changed_path_attributes(svn_log_changed_path2_t *change, const char **attrs) -{ - /* All these arguments are optional. The *_from_word() functions can handle - them for us */ + { ITEM, S_, "modified-path", MODIFIED_PATH, + TRUE, { "?node-kind", "?text-mods", "?prop-mods", NULL }, TRUE }, - change->node_kind = svn_node_kind_from_word( - svn_xml_get_attr_value("node-kind", attrs)); - change->text_modified = svn_tristate__from_word( - svn_xml_get_attr_value("text-mods", attrs)); - change->props_modified = svn_tristate__from_word( - svn_xml_get_attr_value("prop-mods", attrs)); + { 0 } +}; - return SVN_NO_ERROR; -} + +/* Store CDATA into REVPROPS, associated with PROPNAME. If ENCODING is not + NULL, then it must base "base64" and CDATA will be decoded first. + NOTE: PROPNAME must live longer than REVPROPS. */ static svn_error_t * -start_log(svn_ra_serf__xml_parser_t *parser, - void *userData, - svn_ra_serf__dav_props_t name, - const char **attrs) +collect_revprop(apr_hash_t *revprops, + const char *propname, + const svn_string_t *cdata, + const char *encoding) { - log_context_t *log_ctx = userData; - log_state_e state; - - state = parser->state->current_state; + apr_pool_t *result_pool = apr_hash_pool_get(revprops); + const svn_string_t *decoded; - if (state == NONE && - strcmp(name.name, "log-report") == 0) + if (encoding) { - push_state(parser, log_ctx, REPORT, attrs); + /* Check for a known encoding type. This is easy -- there's + only one. */ + if (strcmp(encoding, "base64") != 0) + { + return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, + _("Unsupported encoding '%s'"), + encoding); + } + + decoded = svn_base64_decode_string(cdata, result_pool); } - else if (state == REPORT && - strcmp(name.name, "log-item") == 0) + else { - push_state(parser, log_ctx, ITEM, attrs); + decoded = svn_string_dup(cdata, result_pool); } - else if (state == ITEM) + + /* Caller has ensured PROPNAME has sufficient lifetime. */ + svn_hash_sets(revprops, propname, decoded); + + return SVN_NO_ERROR; +} + + +/* Record ACTION on the path in CDATA into PATHS. Other properties about + the action are pulled from ATTRS. */ +static svn_error_t * +collect_path(apr_hash_t *paths, + char action, + const svn_string_t *cdata, + apr_hash_t *attrs) +{ + apr_pool_t *result_pool = apr_hash_pool_get(paths); + svn_log_changed_path2_t *lcp; + const char *copyfrom_path; + const char *copyfrom_rev; + const char *path; + + lcp = svn_log_changed_path2_create(result_pool); + lcp->action = action; + lcp->copyfrom_rev = SVN_INVALID_REVNUM; + + /* COPYFROM_* are only recorded for ADDED_PATH and REPLACED_PATH. */ + copyfrom_path = svn_hash_gets(attrs, "copyfrom-path"); + copyfrom_rev = svn_hash_gets(attrs, "copyfrom-rev"); + if (copyfrom_path && copyfrom_rev) { - log_info_t *info; + svn_revnum_t rev = SVN_STR_TO_REV(copyfrom_rev); - if (strcmp(name.name, SVN_DAV__VERSION_NAME) == 0) - { - push_state(parser, log_ctx, VERSION, attrs); - } - else if (strcmp(name.name, "creator-displayname") == 0) - { - info = push_state(parser, log_ctx, CREATOR, attrs); - } - else if (strcmp(name.name, "date") == 0) - { - info = push_state(parser, log_ctx, DATE, attrs); - } - else if (strcmp(name.name, "comment") == 0) - { - info = push_state(parser, log_ctx, COMMENT, attrs); - } - else if (strcmp(name.name, "revprop") == 0) - { - const char *revprop_name = - svn_xml_get_attr_value("name", attrs); - if (revprop_name == NULL) - return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, - _("Missing name attr in revprop element")); - info = push_state(parser, log_ctx, REVPROP, attrs); - info->revprop_name = apr_pstrdup(info->pool, revprop_name); - } - else if (strcmp(name.name, "has-children") == 0) - { - push_state(parser, log_ctx, HAS_CHILDREN, attrs); - } - else if (strcmp(name.name, "subtractive-merge") == 0) - { - push_state(parser, log_ctx, SUBTRACTIVE_MERGE, attrs); - } - else if (strcmp(name.name, "added-path") == 0) - { - const char *copy_path, *copy_rev_str; - - info = push_state(parser, log_ctx, ADDED_PATH, attrs); - info->tmp_path->action = 'A'; - - copy_path = svn_xml_get_attr_value("copyfrom-path", attrs); - copy_rev_str = svn_xml_get_attr_value("copyfrom-rev", attrs); - if (copy_path && copy_rev_str) - { - svn_revnum_t copy_rev; - - copy_rev = SVN_STR_TO_REV(copy_rev_str); - if (SVN_IS_VALID_REVNUM(copy_rev)) - { - info->tmp_path->copyfrom_path = apr_pstrdup(info->pool, - copy_path); - info->tmp_path->copyfrom_rev = copy_rev; - } - } - - SVN_ERR(read_changed_path_attributes(info->tmp_path, attrs)); - } - else if (strcmp(name.name, "replaced-path") == 0) + if (SVN_IS_VALID_REVNUM(rev)) { - const char *copy_path, *copy_rev_str; - - info = push_state(parser, log_ctx, REPLACED_PATH, attrs); - info->tmp_path->action = 'R'; - - copy_path = svn_xml_get_attr_value("copyfrom-path", attrs); - copy_rev_str = svn_xml_get_attr_value("copyfrom-rev", attrs); - if (copy_path && copy_rev_str) - { - svn_revnum_t copy_rev; - - copy_rev = SVN_STR_TO_REV(copy_rev_str); - if (SVN_IS_VALID_REVNUM(copy_rev)) - { - info->tmp_path->copyfrom_path = apr_pstrdup(info->pool, - copy_path); - info->tmp_path->copyfrom_rev = copy_rev; - } - } - - SVN_ERR(read_changed_path_attributes(info->tmp_path, attrs)); + lcp->copyfrom_path = apr_pstrdup(result_pool, copyfrom_path); + lcp->copyfrom_rev = rev; } - else if (strcmp(name.name, "deleted-path") == 0) - { - info = push_state(parser, log_ctx, DELETED_PATH, attrs); - info->tmp_path->action = 'D'; + } - SVN_ERR(read_changed_path_attributes(info->tmp_path, attrs)); - } - else if (strcmp(name.name, "modified-path") == 0) - { - info = push_state(parser, log_ctx, MODIFIED_PATH, attrs); - info->tmp_path->action = 'M'; + lcp->node_kind = svn_node_kind_from_word(svn_hash_gets(attrs, "node-kind")); + lcp->text_modified = svn_tristate__from_word(svn_hash_gets(attrs, + "text-mods")); + lcp->props_modified = svn_tristate__from_word(svn_hash_gets(attrs, + "prop-mods")); - SVN_ERR(read_changed_path_attributes(info->tmp_path, attrs)); - } - } + path = apr_pstrmemdup(result_pool, cdata->data, cdata->len); + svn_hash_sets(paths, path, lcp); return SVN_NO_ERROR; } -/* - * Set *DECODED_CDATA to a copy of current CDATA being tracked in INFO, - * decoded as necessary, and allocated from INFO->pool.. - */ + +/* Conforms to svn_ra_serf__xml_opened_t */ static svn_error_t * -maybe_decode_log_cdata(const svn_string_t **decoded_cdata, - log_info_t *info) +log_opened(svn_ra_serf__xml_estate_t *xes, + void *baton, + int entered_state, + const svn_ra_serf__dav_props_t *tag, + apr_pool_t *scratch_pool) { - if (info->tmp_encoding) - { - svn_string_t in; - in.data = info->tmp; - in.len = info->tmp_len; - - /* Check for a known encoding type. This is easy -- there's - only one. */ - if (strcmp(info->tmp_encoding, "base64") != 0) - { - return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, - _("Unsupported encoding '%s'"), - info->tmp_encoding); - } + log_context_t *log_ctx = baton; - *decoded_cdata = svn_base64_decode_string(&in, info->pool); - } - else + if (entered_state == ITEM) { - *decoded_cdata = svn_string_ncreate(info->tmp, info->tmp_len, - info->pool); + apr_pool_t *state_pool = svn_ra_serf__xml_state_pool(xes); + + log_ctx->collect_revprops = apr_hash_make(state_pool); + log_ctx->collect_paths = apr_hash_make(state_pool); } + return SVN_NO_ERROR; } + +/* Conforms to svn_ra_serf__xml_closed_t */ static svn_error_t * -end_log(svn_ra_serf__xml_parser_t *parser, - void *userData, - svn_ra_serf__dav_props_t name) +log_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) { - log_context_t *log_ctx = userData; - log_state_e state; - log_info_t *info; - - state = parser->state->current_state; - info = parser->state->private; + log_context_t *log_ctx = baton; - if (state == REPORT && - strcmp(name.name, "log-report") == 0) - { - svn_ra_serf__xml_pop_state(parser); - } - else if (state == ITEM && - strcmp(name.name, "log-item") == 0) + if (leaving_state == ITEM) { + svn_log_entry_t *log_entry; + const char *rev_str; + if (log_ctx->limit && (log_ctx->nest_level == 0) && (++log_ctx->count > log_ctx->limit)) { return SVN_NO_ERROR; } + log_entry = svn_log_entry_create(scratch_pool); + + /* Pick up the paths from the context. These have the same lifetime + as this state. That is long enough for us to pass the paths to + the receiver callback. */ + if (apr_hash_count(log_ctx->collect_paths) > 0) + { + log_entry->changed_paths = log_ctx->collect_paths; + log_entry->changed_paths2 = log_ctx->collect_paths; + } + + /* ... and same story for the collected revprops. */ + log_entry->revprops = log_ctx->collect_revprops; + + log_entry->has_children = svn_hash__get_bool(attrs, + "has-children", + FALSE); + log_entry->subtractive_merge = svn_hash__get_bool(attrs, + "subtractive-merge", + FALSE); + + rev_str = svn_hash_gets(attrs, "revision"); + if (rev_str) + log_entry->revision = SVN_STR_TO_REV(rev_str); + else + log_entry->revision = SVN_INVALID_REVNUM; + /* Give the info to the reporter */ SVN_ERR(log_ctx->receiver(log_ctx->receiver_baton, - info->log_entry, - info->pool)); + log_entry, + scratch_pool)); - if (info->log_entry->has_children) + if (log_entry->has_children) { log_ctx->nest_level++; } - if (! SVN_IS_VALID_REVNUM(info->log_entry->revision)) + if (! SVN_IS_VALID_REVNUM(log_entry->revision)) { SVN_ERR_ASSERT(log_ctx->nest_level); log_ctx->nest_level--; } - svn_pool_destroy(info->pool); - svn_ra_serf__xml_pop_state(parser); + /* These hash tables are going to be unusable once this state's + pool is destroyed. But let's not leave stale pointers in + structures that have a longer life. */ + log_ctx->collect_revprops = NULL; + log_ctx->collect_paths = NULL; } - else if (state == VERSION && - strcmp(name.name, SVN_DAV__VERSION_NAME) == 0) + else if (leaving_state == VERSION) { - info->log_entry->revision = SVN_STR_TO_REV(info->tmp); - info->tmp_len = 0; - svn_ra_serf__xml_pop_state(parser); + svn_ra_serf__xml_note(xes, ITEM, "revision", cdata->data); } - else if (state == CREATOR && - strcmp(name.name, "creator-displayname") == 0) + else if (leaving_state == CREATOR) { if (log_ctx->want_author) { - const svn_string_t *decoded_cdata; - SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, info)); - apr_hash_set(info->log_entry->revprops, SVN_PROP_REVISION_AUTHOR, - APR_HASH_KEY_STRING, decoded_cdata); + SVN_ERR(collect_revprop(log_ctx->collect_revprops, + SVN_PROP_REVISION_AUTHOR, + cdata, + svn_hash_gets(attrs, "encoding"))); } - info->tmp_len = 0; - svn_ra_serf__xml_pop_state(parser); } - else if (state == DATE && - strcmp(name.name, "date") == 0) + else if (leaving_state == DATE) { if (log_ctx->want_date) { - const svn_string_t *decoded_cdata; - SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, info)); - apr_hash_set(info->log_entry->revprops, SVN_PROP_REVISION_DATE, - APR_HASH_KEY_STRING, decoded_cdata); + SVN_ERR(collect_revprop(log_ctx->collect_revprops, + SVN_PROP_REVISION_DATE, + cdata, + svn_hash_gets(attrs, "encoding"))); } - info->tmp_len = 0; - svn_ra_serf__xml_pop_state(parser); } - else if (state == COMMENT && - strcmp(name.name, "comment") == 0) + else if (leaving_state == COMMENT) { if (log_ctx->want_message) { - const svn_string_t *decoded_cdata; - SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, info)); - apr_hash_set(info->log_entry->revprops, SVN_PROP_REVISION_LOG, - APR_HASH_KEY_STRING, decoded_cdata); + SVN_ERR(collect_revprop(log_ctx->collect_revprops, + SVN_PROP_REVISION_LOG, + cdata, + svn_hash_gets(attrs, "encoding"))); } - info->tmp_len = 0; - svn_ra_serf__xml_pop_state(parser); } - else if (state == REVPROP) + else if (leaving_state == REVPROP) { - const svn_string_t *decoded_cdata; - SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, info)); - apr_hash_set(info->log_entry->revprops, info->revprop_name, - APR_HASH_KEY_STRING, decoded_cdata); - info->tmp_len = 0; - svn_ra_serf__xml_pop_state(parser); + apr_pool_t *result_pool = apr_hash_pool_get(log_ctx->collect_revprops); + + SVN_ERR(collect_revprop( + log_ctx->collect_revprops, + apr_pstrdup(result_pool, + svn_hash_gets(attrs, "name")), + cdata, + svn_hash_gets(attrs, "encoding") + )); } - else if (state == HAS_CHILDREN && - strcmp(name.name, "has-children") == 0) + else if (leaving_state == HAS_CHILDREN) { - info->log_entry->has_children = TRUE; - svn_ra_serf__xml_pop_state(parser); + svn_ra_serf__xml_note(xes, ITEM, "has-children", "yes"); } - else if (state == SUBTRACTIVE_MERGE && - strcmp(name.name, "subtractive-merge") == 0) + else if (leaving_state == SUBTRACTIVE_MERGE) { - info->log_entry->subtractive_merge = TRUE; - svn_ra_serf__xml_pop_state(parser); + svn_ra_serf__xml_note(xes, ITEM, "subtractive-merge", "yes"); } - else if ((state == ADDED_PATH && - strcmp(name.name, "added-path") == 0) || - (state == DELETED_PATH && - strcmp(name.name, "deleted-path") == 0) || - (state == MODIFIED_PATH && - strcmp(name.name, "modified-path") == 0) || - (state == REPLACED_PATH && - strcmp(name.name, "replaced-path") == 0)) + else { - char *path; - - path = apr_pstrmemdup(info->pool, info->tmp, info->tmp_len); - info->tmp_len = 0; + char action; + + if (leaving_state == ADDED_PATH) + action = 'A'; + else if (leaving_state == REPLACED_PATH) + action = 'R'; + else if (leaving_state == DELETED_PATH) + action = 'D'; + else + { + SVN_ERR_ASSERT(leaving_state == MODIFIED_PATH); + action = 'M'; + } - apr_hash_set(info->log_entry->changed_paths2, path, APR_HASH_KEY_STRING, - info->tmp_path); - svn_ra_serf__xml_pop_state(parser); + SVN_ERR(collect_path(log_ctx->collect_paths, action, cdata, attrs)); } return SVN_NO_ERROR; } -static svn_error_t * -cdata_log(svn_ra_serf__xml_parser_t *parser, - void *userData, - const char *data, - apr_size_t len) -{ - log_context_t *log_ctx = userData; - log_state_e state; - log_info_t *info; - - UNUSED_CTX(log_ctx); - - state = parser->state->current_state; - info = parser->state->private; - - switch (state) - { - case VERSION: - case CREATOR: - case DATE: - case COMMENT: - case REVPROP: - case ADDED_PATH: - case REPLACED_PATH: - case DELETED_PATH: - case MODIFIED_PATH: - svn_ra_serf__expand_string(&info->tmp, &info->tmp_len, - data, len, info->pool); - break; - default: - break; - } - - return SVN_NO_ERROR; -} static svn_error_t * create_log_body(serf_bucket_t **body_bkt, @@ -632,11 +515,11 @@ svn_ra_serf__get_log(svn_ra_session_t *ra_session, log_context_t *log_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; - svn_ra_serf__xml_parser_t *parser_ctx; + svn_ra_serf__xml_context_t *xmlctx; svn_boolean_t want_custom_revprops; svn_revnum_t peg_rev; svn_error_t *err; - const char *relative_url, *basecoll_url, *req_url; + const char *req_url; log_ctx = apr_pcalloc(pool, sizeof(*log_ctx)); log_ctx->pool = pool; @@ -651,7 +534,6 @@ svn_ra_serf__get_log(svn_ra_session_t *ra_session, log_ctx->include_merged_revisions = include_merged_revisions; log_ctx->revprops = revprops; log_ctx->nest_level = 0; - log_ctx->done = FALSE; want_custom_revprops = FALSE; if (revprops) @@ -689,14 +571,18 @@ svn_ra_serf__get_log(svn_ra_session_t *ra_session, /* At this point, we may have a deleted file. So, we'll match ra_neon's * behavior and use the larger of start or end as our 'peg' rev. */ - peg_rev = (start > end) ? start : end; + peg_rev = (start == SVN_INVALID_REVNUM || start > end) ? start : end; - SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session, - NULL, NULL, peg_rev, NULL, pool)); + SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, + session, NULL /* conn */, + NULL /* url */, peg_rev, + pool, pool)); - req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool); - - handler = apr_pcalloc(pool, sizeof(*handler)); + xmlctx = svn_ra_serf__xml_context_create(log_ttable, + log_opened, log_closed, NULL, + log_ctx, + pool); + handler = svn_ra_serf__create_expat_handler(xmlctx, pool); handler->method = "REPORT"; handler->path = req_url; @@ -706,27 +592,12 @@ svn_ra_serf__get_log(svn_ra_session_t *ra_session, handler->conn = session->conns[0]; handler->session = session; - parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx)); - - parser_ctx->pool = pool; - parser_ctx->user_data = log_ctx; - parser_ctx->start = start_log; - parser_ctx->end = end_log; - parser_ctx->cdata = cdata_log; - parser_ctx->done = &log_ctx->done; - parser_ctx->status_code = &log_ctx->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(&log_ctx->done, session, pool); + err = svn_ra_serf__context_run_one(handler, pool); SVN_ERR(svn_error_compose_create( - svn_ra_serf__error_on_status(log_ctx->status_code, + svn_ra_serf__error_on_status(handler->sline, req_url, - parser_ctx->location), + handler->location), err)); return SVN_NO_ERROR; |