diff options
Diffstat (limited to 'subversion/libsvn_ra_serf/getlocations.c')
-rw-r--r-- | subversion/libsvn_ra_serf/getlocations.c | 177 |
1 files changed, 47 insertions, 130 deletions
diff --git a/subversion/libsvn_ra_serf/getlocations.c b/subversion/libsvn_ra_serf/getlocations.c index 6d3fa97..1ae4f82 100644 --- a/subversion/libsvn_ra_serf/getlocations.c +++ b/subversion/libsvn_ra_serf/getlocations.c @@ -27,6 +27,7 @@ #include <serf.h> +#include "svn_hash.h" #include "svn_path.h" #include "svn_pools.h" #include "svn_ra.h" @@ -41,18 +42,11 @@ /* * This enum represents the current state of our XML parsing for a REPORT. */ -typedef enum loc_state_e { +enum loc_state_e { + INITIAL = 0, REPORT, LOCATION -} loc_state_e; - -typedef struct loc_state_list_t { - /* The current state that we are in now. */ - loc_state_e state; - - /* The previous state we were in. */ - struct loc_state_list_t *prev; -} loc_state_list_t; +}; typedef struct loc_context_t { /* pool to allocate memory from */ @@ -66,115 +60,50 @@ typedef struct loc_context_t { /* Returned location hash */ apr_hash_t *paths; - /* Current state we're in */ - loc_state_list_t *state; - loc_state_list_t *free_state; - - int status_code; - - svn_boolean_t done; } loc_context_t; - -static void -push_state(loc_context_t *loc_ctx, loc_state_e state) -{ - loc_state_list_t *new_state; - - if (!loc_ctx->free_state) - { - new_state = apr_palloc(loc_ctx->pool, sizeof(*loc_ctx->state)); - } - else - { - new_state = loc_ctx->free_state; - loc_ctx->free_state = loc_ctx->free_state->prev; - } - new_state->state = state; - - /* Add it to the state chain. */ - new_state->prev = loc_ctx->state; - loc_ctx->state = new_state; -} +#define D_ "DAV:" +#define S_ SVN_XML_NAMESPACE +static const svn_ra_serf__xml_transition_t getloc_ttable[] = { + { INITIAL, S_, "get-locations-report", REPORT, + FALSE, { NULL }, FALSE }, -static void pop_state(loc_context_t *loc_ctx) -{ - loc_state_list_t *free_state; - free_state = loc_ctx->state; - /* advance the current state */ - loc_ctx->state = loc_ctx->state->prev; - free_state->prev = loc_ctx->free_state; - loc_ctx->free_state = free_state; -} + { REPORT, S_, "location", LOCATION, + FALSE, { "?rev", "?path", NULL }, TRUE }, -static svn_error_t * -start_getloc(svn_ra_serf__xml_parser_t *parser, - void *userData, - svn_ra_serf__dav_props_t name, - const char **attrs) -{ - loc_context_t *loc_ctx = userData; - - if (!loc_ctx->state && strcmp(name.name, "get-locations-report") == 0) - { - push_state(loc_ctx, REPORT); - } - else if (loc_ctx->state && - loc_ctx->state->state == REPORT && - strcmp(name.name, "location") == 0) - { - svn_revnum_t rev = SVN_INVALID_REVNUM; - const char *revstr, *path; - - revstr = svn_xml_get_attr_value("rev", attrs); - if (revstr) - { - rev = SVN_STR_TO_REV(revstr); - } - - path = svn_xml_get_attr_value("path", attrs); - - if (SVN_IS_VALID_REVNUM(rev) && path) - { - apr_hash_set(loc_ctx->paths, - apr_pmemdup(loc_ctx->pool, &rev, sizeof(rev)), - sizeof(rev), - apr_pstrdup(loc_ctx->pool, path)); - } - } - - return SVN_NO_ERROR; -} + { 0 } +}; + +/* Conforms to svn_ra_serf__xml_closed_t */ static svn_error_t * -end_getloc(svn_ra_serf__xml_parser_t *parser, - void *userData, - svn_ra_serf__dav_props_t name) +getloc_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) { - loc_context_t *loc_ctx = userData; - loc_state_list_t *cur_state; - - if (!loc_ctx->state) - { - return SVN_NO_ERROR; - } + loc_context_t *loc_ctx = baton; + const char *revstr; + const char *path; - cur_state = loc_ctx->state; + SVN_ERR_ASSERT(leaving_state == LOCATION); - if (cur_state->state == REPORT && - strcmp(name.name, "get-locations-report") == 0) - { - pop_state(loc_ctx); - } - else if (cur_state->state == LOCATION && - strcmp(name.name, "location") == 0) + revstr = svn_hash_gets(attrs, "rev"); + path = svn_hash_gets(attrs, "path"); + if (revstr != NULL && path != NULL) { - pop_state(loc_ctx); + svn_revnum_t rev = SVN_STR_TO_REV(revstr); + apr_hash_set(loc_ctx->paths, + apr_pmemdup(loc_ctx->pool, &rev, sizeof(rev)), sizeof(rev), + apr_pstrdup(loc_ctx->pool, path)); } return SVN_NO_ERROR; } + /* Implements svn_ra_serf__request_body_delegate_t */ static svn_error_t * create_get_locations_body(serf_bucket_t **body_bkt, @@ -228,8 +157,8 @@ svn_ra_serf__get_locations(svn_ra_session_t *ra_session, loc_context_t *loc_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, *req_url; + svn_ra_serf__xml_context_t *xmlctx; + const char *req_url; svn_error_t *err; loc_ctx = apr_pcalloc(pool, sizeof(*loc_ctx)); @@ -237,18 +166,20 @@ svn_ra_serf__get_locations(svn_ra_session_t *ra_session, loc_ctx->path = path; loc_ctx->peg_revision = peg_revision; loc_ctx->location_revisions = location_revisions; - loc_ctx->done = FALSE; loc_ctx->paths = apr_hash_make(loc_ctx->pool); *locations = loc_ctx->paths; - SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session, - NULL, NULL, peg_revision, NULL, - pool)); - - req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool); + SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, + session, NULL /* conn */, + NULL /* url */, peg_revision, + pool, pool)); - handler = apr_pcalloc(pool, sizeof(*handler)); + xmlctx = svn_ra_serf__xml_context_create(getloc_ttable, + NULL, getloc_closed, NULL, + loc_ctx, + pool); + handler = svn_ra_serf__create_expat_handler(xmlctx, pool); handler->method = "REPORT"; handler->path = req_url; @@ -258,26 +189,12 @@ svn_ra_serf__get_locations(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 = loc_ctx; - parser_ctx->start = start_getloc; - parser_ctx->end = end_getloc; - parser_ctx->status_code = &loc_ctx->status_code; - parser_ctx->done = &loc_ctx->done; - - 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(&loc_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(loc_ctx->status_code, + svn_ra_serf__error_on_status(handler->sline, req_url, - parser_ctx->location), + handler->location), err)); return SVN_NO_ERROR; |