Author: gstein
Date: Thu Jun 7 20:55:09 2012
New Revision: 1347790
URL: http://svn.apache.org/viewvc?rev=1347790&view=rev
Log:
Convert the MERGE request code (ie. the final step in a commit) over
to the new XML processing code.
The old code would capture all properties in the merge response, but
then only examine a few. We now capture just the properties we need,
and ignore the rest.
* subversion/libsvn_ra_serf/ra_serf.h:
(svn_ra_serf__xml_closed_t): update docstring
(svn_ra_serf__xml_transition_t): clarify docstring for COLLECT_CDATA
(svn_ra_serf__merge_context_t): removed typedef.
(svn_ra_serf__merge_get_done_ptr,
svn_ra_serf__merge_get_commit_info,
svn_ra_serf__merge_get_status): removed. no longer needed.
(svn_ra_serf__merge_create_req): renamed to ...
(svn_ra_serf__run_merge): ... this. rather than returning an opaque
context, we return the final commit info and the response code.
switched to dual-pool semantics.
* subversion/libsvn_ra_serf/merge.c:
(NONE, NAME, IGNORE_PROP_NAME, NEED_PROP_NAME): removed unused states
(BASELINE, COLLECTION, CHECKED_IN, VERSION_NAME, POST_COMMIT_ERR):
new parse states
(resource_type_e): removed. unused.
(merge_info_t): removed. unused.
(svn_ra_serf__merge_context_t): typedef moved here. DONE member
removed, in favor of the handler's DONE flag.
(merge_ttable): now compiled. adjusted many flags and introduced new
states for the properties that we capture.
(merge_closed): new function to handle the processing
(push_state, start_merge, end_merge, cdata_merge): removed from
compilation, but left in file to keep the "diff" reasonable. will
be removed in a future commit.
(svn_ra_serf__merge_create_req): renamed to ...
(svn_ra_serf__run_merge): ... this. adjusted params to return the
necessary info. switched to dual-pool. switch over to the new xml
processing. actually run the request here.
(svn_ra_serf__merge_get_done_ptr,
svn_ra_serf__merge_get_commit_info,
svn_ra_serf__merge_get_status): removed. no longer needed.
* subversion/libsvn_ra_serf/commit.c:
(close_edit): switch call to run_merge() and then deal with the
results, rather than a bunch of dumb opaque type handling. narrow
the scope of the HANDLER localvar.
Modified:
subversion/trunk/subversion/libsvn_ra_serf/commit.c
subversion/trunk/subversion/libsvn_ra_serf/merge.c
subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
Modified: subversion/trunk/subversion/libsvn_ra_serf/commit.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/commit.c?rev=1347790&r1=1347789&r2=1347790&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/commit.c Thu Jun 7 20:55:09 2012
@@ -2135,40 +2135,37 @@ close_edit(void *edit_baton,
apr_pool_t *pool)
{
commit_context_t *ctx = edit_baton;
- svn_ra_serf__merge_context_t *merge_ctx;
- svn_ra_serf__handler_t *handler;
- svn_boolean_t *merge_done;
const char *merge_target =
ctx->activity_url ? ctx->activity_url : ctx->txn_url;
+ const svn_commit_info_t *commit_info;
+ int response_code;
/* MERGE our activity */
- SVN_ERR(svn_ra_serf__merge_create_req(&merge_ctx, ctx->session,
- ctx->session->conns[0],
- merge_target,
- ctx->lock_tokens,
- ctx->keep_locks,
- pool));
-
- merge_done = svn_ra_serf__merge_get_done_ptr(merge_ctx);
+ SVN_ERR(svn_ra_serf__run_merge(&commit_info, &response_code,
+ ctx->session,
+ ctx->session->conns[0],
+ merge_target,
+ ctx->lock_tokens,
+ ctx->keep_locks,
+ pool, pool));
- SVN_ERR(svn_ra_serf__context_run_wait(merge_done, ctx->session, pool));
-
- if (svn_ra_serf__merge_get_status(merge_ctx) != 200)
+ if (response_code != 200)
{
return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("MERGE request failed: returned %d "
"(during commit)"),
- svn_ra_serf__merge_get_status(merge_ctx));
+ response_code);
}
/* Inform the WC that we did a commit. */
if (ctx->callback)
- SVN_ERR(ctx->callback(svn_ra_serf__merge_get_commit_info(merge_ctx),
- ctx->callback_baton, pool));
+ SVN_ERR(ctx->callback(commit_info, ctx->callback_baton, pool));
/* If we're using activities, DELETE our completed activity. */
if (ctx->activity_url)
{
+ svn_ra_serf__handler_t *handler;
+
handler = apr_pcalloc(pool, sizeof(*handler));
handler->handler_pool = pool;
handler->method = "DELETE";
Modified: subversion/trunk/subversion/libsvn_ra_serf/merge.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/merge.c?rev=1347790&r1=1347789&r2=1347790&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/merge.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/merge.c Thu Jun 7 20:55:09 2012
@@ -48,7 +48,6 @@
*/
typedef enum merge_state_e {
INITIAL = 0,
- NONE = 0,
MERGE_RESPONSE,
UPDATED_SET,
RESPONSE,
@@ -56,38 +55,21 @@ typedef enum merge_state_e {
PROPSTAT,
PROP,
RESOURCE_TYPE,
- AUTHOR,
- NAME,
- DATE,
- SKIP_HREF,
- IGNORE_PROP_NAME = SKIP_HREF, /* ### leave old name for now */
- 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 svn_ra_serf__merge_context_t
{
apr_pool_t *pool;
@@ -100,67 +82,190 @@ 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. */
- svn_boolean_t done;
-
svn_commit_info_t *commit_info;
-};
-#if 0
-/* ### can't do this yet because we don't have wildcard transitions, which
- ### is needed to capture a property name. */
+} svn_ra_serf__merge_context_t;
+
#define D_ "DAV:"
#define S_ SVN_XML_NAMESPACE
static const svn_ra_serf__xml_transition_t merge_ttable[] = {
- { INITIAL, S_, "merge-response", MERGE_RESPONSE,
+ { INITIAL, D_, "merge-response", MERGE_RESPONSE,
FALSE, { NULL }, FALSE },
- { MERGE_RESPONSE, S_, "updated-set", UPDATED_SET,
+ { MERGE_RESPONSE, D_, "updated-set", UPDATED_SET,
FALSE, { NULL }, FALSE },
{ UPDATED_SET, D_, "response", RESPONSE,
- FALSE, { NULL }, FALSE },
+ FALSE, { NULL }, TRUE },
{ RESPONSE, D_, "href", HREF,
- FALSE, { NULL }, FALSE },
+ TRUE, { NULL }, TRUE },
{ RESPONSE, D_, "propstat", PROPSTAT,
FALSE, { NULL }, FALSE },
- { PROPSTAT, D_, "prop", PROP,
- FALSE, { NULL }, FALSE },
-
#if 0
/* Not needed. */
{ PROPSTAT, D_, "status", STATUS,
FALSE, { NULL }, FALSE },
#endif
+ { PROPSTAT, D_, "prop", PROP,
+ FALSE, { NULL }, FALSE },
+
{ PROP, D_, "resourcetype", RESOURCE_TYPE,
FALSE, { NULL }, FALSE },
{ RESOURCE_TYPE, D_, "baseline", BASELINE,
- FALSE, { NULL }, FALSE },
+ FALSE, { NULL }, TRUE },
{ RESOURCE_TYPE, D_, "collection", COLLECTION,
- FALSE, { NULL }, FALSE },
+ FALSE, { NULL }, TRUE },
{ PROP, D_, "checked-in", SKIP_HREF,
FALSE, { NULL }, FALSE },
- { PROP, "*", "*", PROP_VAL,
- FALSE, { NULL }, FALSE },
+ { SKIP_HREF, D_, "href", CHECKED_IN,
+ TRUE, { NULL }, TRUE },
- { SKIP_HREF, D_, "href", PROP_VAL,
- FALSE, { NULL }, FALSE },
+ { 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 }
};
-#endif
+/* Conforms to svn_ra_serf__xml_closed_t */
+static svn_error_t *
+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 *merge_ctx = baton;
+
+ if (leaving_state == RESPONSE)
+ {
+ const char *rtype;
+
+ 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 *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
+ merge_ctx->commit_info->revision = SVN_INVALID_REVNUM;
+
+ 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 = 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(merge_ctx->session)
+ && merge_ctx->session->wc_callbacks->push_wc_prop)
+ {
+ const char *checked_in;
+ svn_string_t checked_in_str;
+
+ 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(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));
+ }
+ }
+ }
+ else if (leaving_state == BASELINE)
+ {
+ svn_ra_serf__xml_note(xes, RESPONSE, "resourcetype", "baseline");
+ }
+ else if (leaving_state == COLLECTION)
+ {
+ svn_ra_serf__xml_note(xes, RESPONSE, "resourcetype", "collection");
+ }
+ else
+ {
+ const char *name;
+ const char *value = cdata->data;
+
+ if (leaving_state == HREF)
+ {
+ name = "href";
+ value = svn_urlpath__canonicalize(value, scratch_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
+ SVN_ERR_MALFUNCTION();
+
+ svn_ra_serf__xml_note(xes, RESPONSE, name, value);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+#if 0
-
static merge_info_t *
push_state(svn_ra_serf__xml_parser_t *parser,
svn_ra_serf__merge_context_t *ctx,
@@ -451,6 +556,9 @@ cdata_merge(svn_ra_serf__xml_parser_t *p
return SVN_NO_ERROR;
}
+#endif /* 0 */
+
+
static svn_error_t *
setup_merge_headers(serf_bucket_t *headers,
void *baton,
@@ -563,21 +671,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;
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;
@@ -585,13 +695,16 @@ 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->handler_pool = pool;
handler->method = "MERGE";
handler->path = merge_ctx->merge_url;
handler->body_delegate = create_merge_body;
@@ -599,44 +712,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;
-
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->handler->sline.code;
-}
Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=1347790&r1=1347789&r2=1347790&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Thu Jun 7 20:55:09
2012
@@ -642,8 +642,11 @@ typedef svn_error_t *
non-NULL and contain the collected cdata.
If attribute collection was enabled for this state, then ATTRS will
- contain the attributes collected for this element only. Use
- svn_ra_serf__xml_gather_since() to gather up data from outer states.
+ contain the attributes collected for this element only, along with
+ any values stored via svn_ra_serf__xml_note().
+
+ Use svn_ra_serf__xml_gather_since() to gather up data from outer states.
+
ATTRS is char* -> char*.
Temporary allocations may be made in SCRATCH_POOL. */
@@ -687,7 +690,8 @@ typedef struct svn_ra_serf__xml_transiti
/* Moving to this state */
int to_state;
- /* Should the cdata of NAME be collected? */
+ /* Should the cdata of NAME be collected? Note that CUSTOM_CLOSE should
+ be TRUE in order to capture this cdata. */
svn_boolean_t collect_cdata;
/* Which attributes of NAME should be collected? Terminate with NULL.
@@ -1240,17 +1244,6 @@ svn_ra_serf__get_resource_type(svn_kind_
/** MERGE-related functions **/
-typedef struct svn_ra_serf__merge_context_t svn_ra_serf__merge_context_t;
-
-svn_boolean_t*
-svn_ra_serf__merge_get_done_ptr(svn_ra_serf__merge_context_t *ctx);
-
-svn_commit_info_t*
-svn_ra_serf__merge_get_commit_info(svn_ra_serf__merge_context_t *ctx);
-
-int
-svn_ra_serf__merge_get_status(svn_ra_serf__merge_context_t *ctx);
-
void
svn_ra_serf__merge_lock_token_list(apr_hash_t *lock_tokens,
const char *parent,
@@ -1264,13 +1257,16 @@ svn_ra_serf__merge_lock_token_list(apr_h
client. If KEEP_LOCKS is set, instruct the server to not release
locks set on the paths included in this commit. */
svn_error_t *
-svn_ra_serf__merge_create_req(svn_ra_serf__merge_context_t **merge_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);
+
/** OPTIONS-related functions **/