diff options
Diffstat (limited to 'subversion/libsvn_ra_serf')
-rw-r--r-- | subversion/libsvn_ra_serf/getlocks.c | 19 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/inherited_props.c | 237 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/locks.c | 45 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/log.c | 2 | ||||
-rw-r--r-- | subversion/libsvn_ra_serf/update.c | 19 |
5 files changed, 137 insertions, 185 deletions
diff --git a/subversion/libsvn_ra_serf/getlocks.c b/subversion/libsvn_ra_serf/getlocks.c index 04e5561799361..df201a7506f55 100644 --- a/subversion/libsvn_ra_serf/getlocks.c +++ b/subversion/libsvn_ra_serf/getlocks.c @@ -116,6 +116,7 @@ getlocks_closed(svn_ra_serf__xml_estate_t *xes, if (leaving_state == LOCK) { const char *path = svn_hash_gets(attrs, "path"); + const char *token = svn_hash_gets(attrs, "token"); svn_boolean_t save_lock = FALSE; /* Filter out unwanted paths. Since Subversion only allows @@ -128,6 +129,12 @@ getlocks_closed(svn_ra_serf__xml_estate_t *xes, c) we've asked for depth=files or depth=immediates, and this lock is on an immediate child of our query path. */ + if (! token) + { + /* A lock without a token is not a lock; just an answer that there + is no lock on the node. */ + save_lock = FALSE; + } if (strcmp(lock_ctx->path, path) == 0 || lock_ctx->requested_depth == svn_depth_infinity) { @@ -154,7 +161,7 @@ getlocks_closed(svn_ra_serf__xml_estate_t *xes, them may have not been sent, so the value will be NULL. */ lock.path = path; - lock.token = svn_hash_gets(attrs, "token"); + lock.token = token; lock.owner = svn_hash_gets(attrs, "owner"); lock.comment = svn_hash_gets(attrs, "comment"); @@ -234,6 +241,7 @@ svn_ra_serf__get_locks(svn_ra_session_t *ra_session, svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *req_url, *rel_path; + svn_error_t *err; req_url = svn_path_url_add_component2(session->session_url.path, path, pool); SVN_ERR(svn_ra_serf__get_relative_path(&rel_path, req_url, session, @@ -260,7 +268,14 @@ svn_ra_serf__get_locks(svn_ra_session_t *ra_session, handler->body_delegate = create_getlocks_body; handler->body_delegate_baton = lock_ctx; - SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); + err = svn_ra_serf__context_run_one(handler, pool); + + /* Wrap the server generated error for an unsupported report with the + documented error for this ra function. */ + if (svn_error_find_cause(err, SVN_ERR_UNSUPPORTED_FEATURE)) + err = svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err, NULL); + + SVN_ERR(err); /* We get a 404 when a path doesn't exist in HEAD, but it might have existed earlier (E.g. 'svn ls http://s/svn/trunk/file@1' */ diff --git a/subversion/libsvn_ra_serf/inherited_props.c b/subversion/libsvn_ra_serf/inherited_props.c index 54eae0b5be7cd..f1172e7b6815c 100644 --- a/subversion/libsvn_ra_serf/inherited_props.c +++ b/subversion/libsvn_ra_serf/inherited_props.c @@ -41,7 +41,7 @@ /* The current state of our XML parsing. */ typedef enum iprops_state_e { - NONE = 0, + INITIAL = 0, IPROPS_REPORT, IPROPS_ITEM, IPROPS_PATH, @@ -61,18 +61,12 @@ typedef struct iprops_context_t { /* The repository's root URL. */ const char *repos_root_url; - /* Current CDATA values*/ - svn_stringbuf_t *curr_path; + /* Current property name */ svn_stringbuf_t *curr_propname; - svn_stringbuf_t *curr_propval; - const char *curr_prop_val_encoding; /* Current element in IPROPS. */ svn_prop_inherited_item_t *curr_iprop; - /* Serf context completion flag for svn_ra_serf__context_run_wait() */ - svn_boolean_t done; - /* Path we are finding inherited properties for. This is relative to the RA session passed to svn_ra_serf__get_inherited_props. */ const char *path; @@ -80,162 +74,121 @@ typedef struct iprops_context_t { svn_revnum_t revision; } iprops_context_t; +#define S_ SVN_XML_NAMESPACE +static const svn_ra_serf__xml_transition_t iprops_table[] = { + { INITIAL, S_, SVN_DAV__INHERITED_PROPS_REPORT, IPROPS_REPORT, + FALSE, { NULL }, FALSE }, + + { IPROPS_REPORT, S_, SVN_DAV__IPROP_ITEM, IPROPS_ITEM, + FALSE, { NULL }, TRUE }, + + { IPROPS_ITEM, S_, SVN_DAV__IPROP_PATH, IPROPS_PATH, + TRUE, { NULL }, TRUE }, + + { IPROPS_ITEM, S_, SVN_DAV__IPROP_PROPNAME, IPROPS_PROPNAME, + TRUE, { NULL }, TRUE }, + + { IPROPS_ITEM, S_, SVN_DAV__IPROP_PROPVAL, IPROPS_PROPVAL, + TRUE, { "?V:encoding", NULL }, TRUE }, + + { 0 } +}; + +/* Conforms to svn_ra_serf__xml_opened_t */ static svn_error_t * -start_element(svn_ra_serf__xml_parser_t *parser, - svn_ra_serf__dav_props_t name, - const char **attrs, +iprops_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) { - iprops_context_t *iprops_ctx = parser->user_data; - iprops_state_e state; + iprops_context_t *iprops_ctx = baton; - state = parser->state->current_state; - if (state == NONE - && strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0) + if (entered_state == IPROPS_ITEM) { - svn_ra_serf__xml_push_state(parser, IPROPS_REPORT); - } - else if (state == IPROPS_REPORT && - strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0) - { - svn_stringbuf_setempty(iprops_ctx->curr_path); svn_stringbuf_setempty(iprops_ctx->curr_propname); - svn_stringbuf_setempty(iprops_ctx->curr_propval); - iprops_ctx->curr_prop_val_encoding = NULL; - iprops_ctx->curr_iprop = NULL; - svn_ra_serf__xml_push_state(parser, IPROPS_ITEM); - } - else if (state == IPROPS_ITEM && - strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0) - { - const char *prop_val_encoding = svn_xml_get_attr_value("encoding", - attrs); - iprops_ctx->curr_prop_val_encoding = apr_pstrdup(iprops_ctx->pool, - prop_val_encoding); - svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL); - } - else if (state == IPROPS_ITEM && - strcmp(name.name, SVN_DAV__IPROP_PATH) == 0) - { - svn_ra_serf__xml_push_state(parser, IPROPS_PATH); - } - else if (state == IPROPS_ITEM && - strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0) - { - svn_ra_serf__xml_push_state(parser, IPROPS_PROPNAME); - } - else if (state == IPROPS_ITEM && - strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0) - { - svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL); - } + iprops_ctx->curr_iprop = apr_pcalloc(iprops_ctx->pool, + sizeof(*iprops_ctx->curr_iprop)); + + iprops_ctx->curr_iprop->prop_hash = apr_hash_make(iprops_ctx->pool); + } return SVN_NO_ERROR; } +/* 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) +iprops_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) { - iprops_context_t *iprops_ctx = parser->user_data; - iprops_state_e state; - - state = parser->state->current_state; + iprops_context_t *iprops_ctx = baton; - if (state == IPROPS_REPORT && - strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0) + if (leaving_state == IPROPS_ITEM) { - svn_ra_serf__xml_pop_state(parser); + APR_ARRAY_PUSH(iprops_ctx->iprops, svn_prop_inherited_item_t *) = + iprops_ctx->curr_iprop; + + iprops_ctx->curr_iprop = NULL; } - else if (state == IPROPS_PATH - && strcmp(name.name, SVN_DAV__IPROP_PATH) == 0) + else if (leaving_state == IPROPS_PATH) { - iprops_ctx->curr_iprop = apr_palloc( - iprops_ctx->pool, sizeof(svn_prop_inherited_item_t)); + /* Every <iprop-item> has a single <iprop-path> */ + if (iprops_ctx->curr_iprop->path_or_url) + 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, - iprops_ctx->curr_path->data, + cdata->data, iprops_ctx->pool); - iprops_ctx->curr_iprop->prop_hash = apr_hash_make(iprops_ctx->pool); - svn_ra_serf__xml_pop_state(parser); } - else if (state == IPROPS_PROPVAL - && strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0) + else if (leaving_state == IPROPS_PROPNAME) { - const svn_string_t *prop_val; + if (iprops_ctx->curr_propname->len) + return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL); - if (iprops_ctx->curr_prop_val_encoding) - { - svn_string_t encoded_prop_val; + /* Store propname for value */ + svn_stringbuf_set(iprops_ctx->curr_propname, cdata->data); + } + else if (leaving_state == IPROPS_PROPVAL) + { + const char *encoding; + const svn_string_t *val_str; + + if (! iprops_ctx->curr_propname->len) + return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL); - if (strcmp(iprops_ctx->curr_prop_val_encoding, "base64") != 0) - return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL); + encoding = svn_hash_gets(attrs, "V:encoding"); - encoded_prop_val.data = iprops_ctx->curr_propval->data; - encoded_prop_val.len = iprops_ctx->curr_propval->len; - prop_val = svn_base64_decode_string(&encoded_prop_val, - iprops_ctx->pool); + if (encoding) + { + if (strcmp(encoding, "base64") != 0) + return svn_error_createf(SVN_ERR_XML_MALFORMED, + NULL, + _("Got unrecognized encoding '%s'"), + encoding); + + /* Decode into the right pool. */ + val_str = svn_base64_decode_string(cdata, iprops_ctx->pool); } else { - prop_val = svn_string_create_from_buf(iprops_ctx->curr_propval, - iprops_ctx->pool); + /* Copy into the right pool. */ + val_str = svn_string_dup(cdata, iprops_ctx->pool); } svn_hash_sets(iprops_ctx->curr_iprop->prop_hash, apr_pstrdup(iprops_ctx->pool, iprops_ctx->curr_propname->data), - prop_val); - /* Clear current propname and propval in the event there are - multiple properties on the current path. */ + val_str); + /* Clear current propname. */ svn_stringbuf_setempty(iprops_ctx->curr_propname); - svn_stringbuf_setempty(iprops_ctx->curr_propval); - svn_ra_serf__xml_pop_state(parser); - } - else if (state == IPROPS_PROPNAME - && strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0) - { - svn_ra_serf__xml_pop_state(parser); - } - else if (state == IPROPS_ITEM - && strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0) - { - APR_ARRAY_PUSH(iprops_ctx->iprops, svn_prop_inherited_item_t *) = - iprops_ctx->curr_iprop; - 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) -{ - iprops_context_t *iprops_ctx = parser->user_data; - iprops_state_e state = parser->state->current_state; - - switch (state) - { - case IPROPS_PATH: - svn_stringbuf_appendbytes(iprops_ctx->curr_path, data, len); - break; - - case IPROPS_PROPNAME: - svn_stringbuf_appendbytes(iprops_ctx->curr_propname, data, len); - break; - - case IPROPS_PROPVAL: - svn_stringbuf_appendbytes(iprops_ctx->curr_propval, data, len); - break; - - default: - break; } + else + SVN_ERR_MALFUNCTION(); /* Invalid transition table */ return SVN_NO_ERROR; } @@ -281,7 +234,7 @@ svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session, iprops_context_t *iprops_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; const char *req_url; SVN_ERR(svn_ra_serf__get_stable_url(&req_url, @@ -295,19 +248,20 @@ svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session, SVN_ERR_ASSERT(session->repos_root_str); iprops_ctx = apr_pcalloc(scratch_pool, sizeof(*iprops_ctx)); - iprops_ctx->done = FALSE; iprops_ctx->repos_root_url = session->repos_root_str; iprops_ctx->pool = result_pool; - iprops_ctx->curr_path = svn_stringbuf_create_empty(scratch_pool); iprops_ctx->curr_propname = svn_stringbuf_create_empty(scratch_pool); - iprops_ctx->curr_propval = svn_stringbuf_create_empty(scratch_pool); iprops_ctx->curr_iprop = NULL; iprops_ctx->iprops = apr_array_make(result_pool, 1, sizeof(svn_prop_inherited_item_t *)); iprops_ctx->path = path; iprops_ctx->revision = revision; - handler = apr_pcalloc(scratch_pool, sizeof(*handler)); + xmlctx = svn_ra_serf__xml_context_create(iprops_table, + iprops_opened, iprops_closed, NULL, + iprops_ctx, + scratch_pool); + handler = svn_ra_serf__create_expat_handler(xmlctx, scratch_pool); handler->method = "REPORT"; handler->path = req_url; @@ -318,18 +272,6 @@ svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session, handler->body_type = "text/xml"; handler->handler_pool = scratch_pool; - parser_ctx = apr_pcalloc(scratch_pool, sizeof(*parser_ctx)); - - parser_ctx->pool = scratch_pool; - parser_ctx->user_data = iprops_ctx; - parser_ctx->start = start_element; - parser_ctx->end = end_element; - parser_ctx->cdata = cdata_handler; - parser_ctx->done = &iprops_ctx->done; - - handler->response_handler = svn_ra_serf__handle_xml_parser; - handler->response_baton = parser_ctx; - err = svn_ra_serf__context_run_one(handler, scratch_pool); SVN_ERR(svn_error_compose_create( svn_ra_serf__error_on_status(handler->sline, @@ -337,8 +279,7 @@ svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session, handler->location), err)); - if (iprops_ctx->done) - *iprops = iprops_ctx->iprops; + *iprops = iprops_ctx->iprops; return SVN_NO_ERROR; } diff --git a/subversion/libsvn_ra_serf/locks.c b/subversion/libsvn_ra_serf/locks.c index db2d37125a00b..252c30182a5f5 100644 --- a/subversion/libsvn_ra_serf/locks.c +++ b/subversion/libsvn_ra_serf/locks.c @@ -156,11 +156,20 @@ locks_closed(svn_ra_serf__xml_estate_t *xes, if (leaving_state == TIMEOUT) { - if (strcmp(cdata->data, "Infinite") == 0) + if (strcasecmp(cdata->data, "Infinite") == 0) lock_ctx->lock->expiration_date = 0; + else if (strncasecmp(cdata->data, "Second-", 7) == 0) + { + unsigned n; + SVN_ERR(svn_cstring_atoui(&n, cdata->data+7)); + + lock_ctx->lock->expiration_date = apr_time_now() + + apr_time_from_sec(n); + } else - SVN_ERR(svn_time_from_cstring(&lock_ctx->lock->creation_date, - cdata->data, lock_ctx->pool)); + return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, + _("Invalid LOCK timeout value '%s'"), + cdata->data); } else if (leaving_state == HREF) { @@ -362,29 +371,30 @@ svn_error_t * svn_ra_serf__get_lock(svn_ra_session_t *ra_session, svn_lock_t **lock, const char *path, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; + apr_pool_t *scratch_pool = svn_pool_create(result_pool); lock_info_t *lock_ctx; const char *req_url; svn_error_t *err; - req_url = svn_path_url_add_component2(session->session_url.path, path, pool); - - lock_ctx = apr_pcalloc(pool, sizeof(*lock_ctx)); + req_url = svn_path_url_add_component2(session->session_url.path, path, + scratch_pool); - lock_ctx->pool = pool; + lock_ctx = apr_pcalloc(scratch_pool, sizeof(*lock_ctx)); + lock_ctx->pool = result_pool; lock_ctx->path = req_url; - lock_ctx->lock = svn_lock_create(pool); - lock_ctx->lock->path = apr_pstrdup(pool, path); /* be sure */ + lock_ctx->lock = svn_lock_create(result_pool); + lock_ctx->lock->path = apr_pstrdup(result_pool, path); xmlctx = svn_ra_serf__xml_context_create(locks_ttable, NULL, locks_closed, NULL, lock_ctx, - pool); - handler = svn_ra_serf__create_expat_handler(xmlctx, pool); + scratch_pool); + handler = svn_ra_serf__create_expat_handler(xmlctx, scratch_pool); handler->method = "PROPFIND"; handler->path = req_url; @@ -405,7 +415,7 @@ svn_ra_serf__get_lock(svn_ra_session_t *ra_session, lock_ctx->handler = handler; - err = svn_ra_serf__context_run_one(handler, pool); + err = svn_ra_serf__context_run_one(handler, scratch_pool); err = determine_error(handler, err); if (handler->sline.code == 404) @@ -420,7 +430,12 @@ svn_ra_serf__get_lock(svn_ra_session_t *ra_session, _("Server does not support locking features")); } - *lock = lock_ctx->lock; + if (lock_ctx->lock && lock_ctx->lock->token) + *lock = lock_ctx->lock; + else + *lock = NULL; + + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -574,7 +589,7 @@ svn_ra_serf__unlock(svn_ra_session_t *ra_session, { SVN_ERR(svn_ra_serf__get_lock(ra_session, &existing_lock, path, iterpool)); - token = existing_lock->token; + token = existing_lock ? existing_lock->token : NULL; if (!token) { err = svn_error_createf(SVN_ERR_RA_NOT_LOCKED, NULL, diff --git a/subversion/libsvn_ra_serf/log.c b/subversion/libsvn_ra_serf/log.c index 58a57d890ee42..02f2f2995e5fc 100644 --- a/subversion/libsvn_ra_serf/log.c +++ b/subversion/libsvn_ra_serf/log.c @@ -571,7 +571,7 @@ 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_stable_url(&req_url, NULL /* latest_revnum */, session, NULL /* conn */, diff --git a/subversion/libsvn_ra_serf/update.c b/subversion/libsvn_ra_serf/update.c index 06a16c06effd5..88488ff206f52 100644 --- a/subversion/libsvn_ra_serf/update.c +++ b/subversion/libsvn_ra_serf/update.c @@ -329,9 +329,6 @@ struct report_context_t { files/dirs? */ svn_boolean_t add_props_included; - /* Path -> lock token mapping. */ - apr_hash_t *lock_path_tokens; - /* Path -> const char *repos_relpath mapping */ apr_hash_t *switched_paths; @@ -2248,8 +2245,6 @@ end_report(svn_ra_serf__xml_parser_t *parser, info->pool); } - info->lock_token = svn_hash_gets(ctx->lock_path_tokens, info->name); - if (info->lock_token && !info->fetch_props) info->fetch_props = TRUE; @@ -2578,13 +2573,6 @@ set_path(void *report_baton, SVN_ERR(svn_io_file_write_full(report->body_file, buf->data, buf->len, NULL, pool)); - if (lock_token) - { - svn_hash_sets(report->lock_path_tokens, - apr_pstrdup(report->pool, path), - apr_pstrdup(report->pool, lock_token)); - } - return SVN_NO_ERROR; } @@ -2660,12 +2648,6 @@ link_path(void *report_baton, if (!*path) report->root_is_switched = TRUE; - if (lock_token) - { - svn_hash_sets(report->lock_path_tokens, - path, apr_pstrdup(report->pool, lock_token)); - } - return APR_SUCCESS; } @@ -3193,7 +3175,6 @@ make_update_reporter(svn_ra_session_t *ra_session, report->ignore_ancestry = ignore_ancestry; report->send_copyfrom_args = send_copyfrom_args; report->text_deltas = text_deltas; - report->lock_path_tokens = apr_hash_make(report->pool); report->switched_paths = apr_hash_make(report->pool); report->source = src_path; |